所以,你有一个扩展Thread的java类ExampleThread。为了使这个例子简单,让我们说它的run()方法只是sleep()s 10秒钟,然后打印" Hello World"到屏幕。但是,它是这样创建的:
public void startThread() {
//Create local variable
ExampleThread example = new ExampleThread();
example.start();
}
如果我们调用此方法然后主线程继续做其他事情,Hello World是否会被打印?大多数Java对象在没有任何东西可以引用它们的时刻就不复存在了(没有任何东西可以引用'示例',因为它是一个局部变量)。运行线程不同吗?
很抱歉,如果已经提出这个问题,我无法找到任何相关信息。
答案 0 :(得分:0)
大多数Java对象在没有任何东西可以引用它们的时刻就不复存在了......
出于所有实际目的,这是事实,但实际上,垃圾收集器收回对象之前可能会有一段时间。
...没有任何东西可以引用'example',因为它是一个局部变量
你的错误。
首先,example
不是Thread
对象。 example
是变量,引用到Thread
对象。 example
调用的激活记录中存在startThread()
,一旦startThread()
返回,它就不再存在,但堆上存在Thread
对象。并且,...
...还有另一个对你的程序中不可见的引用。
Thread
对象不是线程。它只是您调用example.start()
时创建的实际操作系统线程的代理。在example.start()
返回之前,它已创建一个新的操作系统线程,包括该线程的堆栈。在新线程的堆栈上,在调用run()
方法的下方,调用带有引用Thread
对象的局部变量的私有方法。
隐藏的局部变量是在Thread
返回之前保持run()
不被垃圾收集的原因。 Java程序中的每个线程都有一个对其自己的Thread
对象的隐藏引用。
答案 1 :(得分:0)
即使您没有持有对该线程的引用,它仍然由ThreadGroup
在内部引用。否则,你认为该线程将被垃圾收集器销毁是正确的。所以这里没有特别处理,但这是一个非常明显的原因。
评论中提到的daemon
属性与此无关。如果只剩下守护程序线程,Java虚拟机将关闭,但两种类型的线程都以相同的方式处理。