[在我开始之前,我尝试搜索相关问题,因为我没有找到,我在这里问一个问题]
我正在学习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.
}
我运行了那段代码。似乎线程还活着。当所有线程退出时,程序结束。
我的问题:
otherThread.join()
中没有main()
?我对自己有一些解释(但我不知道我是对的 - 我在这里发帖的原因):
this
引用,因此引用计数再次不为零。我在上述任何解释中都是正确的吗?或者还有其他任何解释吗?
谢谢和问候:)
答案 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。你在这里的想法是相当循环的。