Java多线程:线程对象的引用计数变为零时的行为

时间:2012-07-16 07:21:23

标签: java multithreading garbage-collection reference-counting

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

我正在学习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()中没有main()

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

  • 只要活动,JVM就会保留对该主题的引用。所以引用计数永远不会为零。
  • 执行函数具有隐式this引用,因此引用计数再次不为零。

我在上述任何解释中都是正确的吗?或者还有其他任何解释吗?

谢谢和问候:)

3 个答案:

答案 0 :(得分:13)

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

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

另请注意,引用的数量不是GC用于判断对象是否符合GC条件的数量。如果图表不再可用,那么维护彼此引用的对象图(例如,DOM树)可以符合GC条件。

答案 1 :(得分:4)

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

2。 线程会在完成运行run()方法后立即死亡,但正如您将要知道的那样,每个线程(脚趾,即线程)执行)与Thread类的实例相关联。

3。因此当线程死亡时,它会进入死状态(我这里没有提到线程池),但Thread类的对象与线程仍在那里,但已永久失去其线程性。

4。但是,只有主要方法已经完成,您的线程仍在运行的可能性很大。

5。调用join()并不是一件好事,但应谨慎使用。

答案 2 :(得分:2)

  

当引用计数为零时,该线程不适合GC吗?

没有。当一个线程终止并且没有引用时,它就有资格获得GC。

  

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

见上文。

  

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

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

  

只要JVM处于活动状态,JVM就会保留对该线程的引用。因此引用计数永远不会为零。

正确。

  

执行函数有一个隐含的引用,因此引用计数也不是零。

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