Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程和垃圾收集器_Java_Multithreading_Garbage Collection - Fatal编程技术网

Java线程和垃圾收集器

Java线程和垃圾收集器,java,multithreading,garbage-collection,Java,Multithreading,Garbage Collection,可能重复: 考虑以下类别: class Foo implements Runnable { public Foo () { Thread th = new Thread (this); th.start(); } public run() { ... // long task } } 如果我们通过 new Foo(); new Foo(); new Foo(); new Foo(); (请注意,我们没有保留指向它们的指针) 垃圾收集

可能重复:

考虑以下类别:

class Foo implements Runnable {

  public Foo () {
       Thread th = new Thread (this);
       th.start();
  }

  public run() {
    ... // long task
  }

}
如果我们通过

new Foo();
new Foo();
new Foo();
new Foo();
(请注意,我们没有保留指向它们的指针)

  • 垃圾收集器是否可以在之前删除这些实例
    run()
    中的线程结束了吗?(换句话说:是否有任何参考 到
    Foo
    对象?)

  • 另一方面,GC是否会删除这些实例 在“run()”中的线程结束后,还是我们在浪费内存(“内存泄漏”)

  • 如果其中一个为1。或2。是个问题,正确的方法是什么

  • 谢谢

  • 活动线程引用的任何对象都不能取消分配
  • 是的,“run()”中的线程结束后,GC将删除实例
  • 没问题
  • 线程引用
    Foo
    对象。线程在运行期间始终被引用。因此,它不会被垃圾收集
  • 没有内存泄漏。线程将结束,并在此进程中被垃圾收集和
    Foo
    对象
  • 它应该很好用
  • 在run()中的线程结束之前,垃圾收集器是否可以删除这些实例?(换句话说:是否有任何对Foo对象的引用?)
  • 否。当构造函数运行时,GC不会收集对象。否则,即使是最简单的:

    Customer c = new Customer();
    
    Customer
    的构造函数运行时可能会失败。另一方面,当您启动一个新线程时,thread对象将成为一个新的GC根,因此该对象引用的所有内容都不会被垃圾收集

  • 另一方面,“run()”中的线程结束后,GC会删除这些实例吗?还是我们在浪费内存(“内存泄漏”)
  • 一旦线程完成,它就不再是GC根。如果没有其他代码指向该线程对象,它将被垃圾收集

  • 如果其中一个为1。或2。是个问题,正确的方法是什么
  • 你的代码很好。然而:

    • 从单元测试的角度来看,在构造函数中启动一个新线程是一个糟糕的想法

    • 保留对所有正在运行的线程的引用可能是有益的,例如,如果您想稍后中断这些线程


    在不指定线程组的情况下启动新线程将:

    如果group为null且存在安全管理器,则该组由安全管理器的getThreadGroup方法确定。如果group为null且没有安全管理器,或者安全管理器的getThreadGroup方法返回null,则该组将设置为与创建新线程的线程相同的线程组

    只要线程处于活动状态,组就会保留对该线程的引用,因此在此期间不能对其进行GC

    当线程终止(=当
    run()
    出于任何原因返回时),该线程将从线程组中删除。这发生在从本机代码调用的私有方法
    exit()
    中。这是对线程的最后一次引用丢失并符合GC条件的时间点


    请注意,代码表明
    ThreadGroup
    可以是
    null
    ,但事实并非如此。各种空检查只是为了在出现问题的罕见情况下避免NPE。在
    Thread.init()
    中,如果Java无法确定线程组,您将获得NPE。

    假设您在run方法中创建对象,则当run方法退出时,对象将超出范围,然后可用于垃圾收集。Run只是另一种方法。无论是否使用线程,都不会以任何方式改变此处的垃圾收集行为。您需要关心的是对象何时超出范围,这通常与块范围(方法块、while循环、if块等)有关


    因此,由于您一开始没有保留对对象的任何引用,因此您可能希望将创建对象的逻辑提取到它自己的短期方法中。这样创建的对象就不需要超出该方法的范围

    @MarkoTopolnik:哦,是的!OP正在将
    这个
    传递给
    线程
    构造函数,该构造函数恰好是
    Foo
    的一个实例。然而,这是正确的-如果
    Foo
    有一些状态,所有状态变量都将在GC中生存,因为它们被
    Foo
    引用,而
    Foo
    被线程本身引用。从线程安全的角度来看,在构造函数中启动新线程也是一个糟糕的主意。在这种简单的情况下,可能会出现问题,但如果您对该类进行子类化,并在子类构造函数中初始化了一些最终字段,则在访问它们之前可能不会对它们进行初始化。Foo对象不是在run方法中创建的,而是在main中创建的。只是另一个代码块,你可以很容易地测试它。@Quaternion,可能是的,但另一个问题的措辞真的很“模糊”,很难理解,imho。这不是重复的。链接的问题并没有涉及“在完成之后它是否会被垃圾收集”(我正要特别问这个问题)。它只询问/回答“它在运行时不会被GC’ed”这一方面。在我看来,这个问题更好。这就是游戏化内容监管的结果。东西被标记为重复的,但它显然不是。请告诉我你从哪里得到这个结论。