4

[开始之前我尝试搜索相关问题,因为我没有找到,所以我在这里问一个问题]

我正在学习 Java,下面的场景让我很头疼:

class MyThread extends Thread {
    void run(){
        //a heavy function
    }
}

现在在主线程中,我将此线程调用为:

public static void main(...){
    new MyThread().start();
    System.gc(); //just a request..
    //end of main thread too.
    //Reference to that MyThread object is now zero.
}

我运行了那个代码。看来线程还活着。当所有线程退出时程序结束。

我的问题:

  • 当引用计数为零时,线程是否有资格进行 GC?如果真的符合条件,那么垃圾回收的行为是什么?线程会被终止吗?
  • 我知道这是一件坏事,但是没有otherThread.join()in 的定义是否明确main()

我对自己有一些解释(但我不知道我有多正确——我在这里发帖的原因):

  • 只要线程处于活动状态,JVM 就会保持对线程的引用。所以参考计数永远不会真正为零。
  • 执行函数有一个隐式this引用,所以引用计数再次不为零。

我在上述任何解释中是否正确?还是完全有其他解释?

谢谢并恭祝安康 :)

4

3 回答 3

13

每个正在运行的线程构成 GC 的根。任何可从根之一访问的对象都不符合 GC 条件,并且线程具有对java.lang.Thread实例的线程本地引用(由 返回Thread.currentThread())。所以不,您的线程在结束运行之前不会被 GC,因为Thread可以从正在运行的线程访问实例。

join()我不明白为什么不调用生成的线程会是一件坏事。如果您不在乎生成的线程何时结束,则无需加入它。当最后一个非守护线程停止运行时,应用程序将停止。

另外,请注意,引用的数量并不是 GC 用来判断对象是否符合 GC 条件的数量。如果图不再可访问,则保持相互引用的对象图(例如 DOM 树)可以进行 GC。

于 2012-07-16T07:26:05.613 回答
4

1. JVM will terminate only when all the Non-Daemon thread including the Main thread已终止。(主线程不是 main() 方法)。

2.线程在运行完其run() 方法后将立即死亡,但正如您所知道的,每个线程(toe,即执行线程)都与Thread 类的实例相关联。

3.所以当线程死亡时,它会进入死亡状态(这里我不提线程池),但是与线程关联的Thread类的对象仍然存在,但已经永久失去了它的线程性。

4.但是很有可能你的线程仍然在运行,只有 main 方法完成了。

5.调用join()并没有什么坏处,但要谨慎使用。

于 2012-07-16T07:29:05.953 回答
2

当引用计数为零时,线程是否有资格进行 GC?

不可以。当线程终止并且没有引用时,它就有资格进行 GC 。

如果真的符合条件,那么垃圾回收的行为是什么?线程会被终止吗?

看上面。

我知道这是一件坏事,但是在 main() 中没有 otherThread.join() 的定义是否明确?

这不是一件坏事,而且它的定义非常明确:当所有非守护线程都退出时,JVM 将退出。

只要线程处于活动状态,JVM 就会保持对线程的引用。所以参考计数永远不会真正为零。

正确的。

正在执行的函数有一个隐含的 this 引用,所以引用计数又不为零。

不正确。考虑静态方法。根据定义,执行函数是在活动线程中执行的,因此根据定义,线程是活动的,因此它不能被 GC 处理。你在这里的想法是相当循环的。

于 2012-07-16T10:50:00.697 回答