Java线程和垃圾收集器[复制](Java threads and garbage collecto

2019-06-24 01:44发布

可能重复:
Java线程垃圾收集或不

考虑下面的类:

class Foo implements Runnable {

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

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

}

如果我们创建的几个实例Foo这样做

new Foo();
new Foo();
new Foo();
new Foo();

(注意,我们不是指针保持他们)。

  1. 能的那些情况下被垃圾收集器在线程之前被去除run()结束? (换句话说:是否有到任何参考Foo对象?)

  2. 而且,在另一方面,将这些实例可以通过运行`()”端线后的GC删除,还是我们浪费存储器(‘内存泄漏’)?

  3. 如果任1或2是一个问题,什么是应该做的正确方法?

谢谢

Answer 1:

  1. 这是由活动线程引用的任何对象可以不被解除分配。
  2. 是的,情况会由GC在运行`()”端线后取出。
  3. 没问题。


Answer 2:

  1. 能的那些情况下被垃圾收集器在运行中的线程之前被移除()结束? (换句话说:是否有到富对象的任何引用?)

否。虽然构造函数运行GC不会收集的对象。 否则,即使是最简单的:

Customer c = new Customer();

的构造而可能失败Customer正在运行。 在当你开始一个新的线程另一方面,线程对象将成为一个新的GC根 ,所以该对象引用一切都没有垃圾收集的对象。

  1. 而且,在另一方面,将这些实例可以通过运行`()”端线后的GC删除,还是我们浪费存储器(‘内存泄漏’)?

一旦线程完成,它不再是一个GC根。 如果没有其他代码指向该线程对象,这将是垃圾收集。

  1. 如果任1或2是一个问题,什么是应该做的正确方法?

您的代码就好了。 然而:

  • 在开始构造一个新的线程是从视功能单元测试点差的主意

  • 如果你想以后中断这些线程如保持一个参考的所有正在运行的线程可能是有益的。



Answer 3:

开始一个新的线程,而无需指定线程组将其添加到默认组 :

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

该集团将保留对线程的引用,只要它是活的,所以它不能在这段时间内GC'd。

当一个线程终止(=当run()返回无论何种原因),该线程被从线程组中删除。 这发生在私有方法exit()这是从本机代码调用。 这是在时间点的最后一个参考线丢失,变得适合GC。

请注意,代码表示ThreadGroup可以为null ,但事实并非如此。 各种空的检查只是为了避免在出现问题的极少数情况下的NPE。 在Thread.init()你会得到的NPE如果用Java代码无法确定一个线程组。



Answer 4:

  1. Foo对象由线程引用。 线程在其上运行的所有时间引用。 因此,它不会被垃圾收集。
  2. 没有内存泄漏。 螺纹将结束,将垃圾收集Foo对象在这个过程中也是如此。
  3. 它应该很好地工作。


Answer 5:

假设你正在创建中的run方法的对象,对象将超出范围时run方法退出,然后将可用于垃圾收集。 润是另一种方法。 使用线程与否不以任何方式改变这里的垃圾收集行为。 所有你需要关心的是,当对象超出范围,这一般依赖于块作用域(方法块,while循环,if块,等等)。

所以,既然你们不守来开始与对象的任何引用,你可能要提取创建该对象到它自己的短暂的方法的逻辑。 这样,所创建的对象将不会需要不断超越该方法的范围。



文章来源: Java threads and garbage collector [duplicate]