为什么不能通过将线程的引用设置为 null 并让垃圾收集器将其删除来终止线程?它和其他任何物体一样,不是吗?
例子:
Thread t = new Thread(new Runnable() {
public void run() {
//...
}
}).start;
t = null;
为什么不能通过将线程的引用设置为 null 并让垃圾收集器将其删除来终止线程?它和其他任何物体一样,不是吗?
例子:
Thread t = new Thread(new Runnable() {
public void run() {
//...
}
}).start;
t = null;
它和其他任何物体一样,不是吗?
不,这不对。它表示非内存资源。您是否期望一个文件被删除,因为代表它的一个对象被垃圾回收了?
事实上,在垃圾回收方面,一个Thread
对象与“任何其他”对象非常不同,因为线程本身就是可达性树的根,因此字段(或堆栈上的局部变量)引用的任何对象根据定义,表示正在运行的线程的 Thread 对象不符合垃圾收集条件。
JLS第 12.6节这样说:
“可达对象是可以从任何活动线程的任何潜在持续计算中访问的任何对象。” .
由此我们可以推断出活动线程是隐式可访问的,只要它们还活着,就不会被垃圾收集。是否存在对 Thread 对象的可达引用无关紧要,尽管(如@Jon Skeet 所说)线程确实隐含地持有对其自己的 Thread 对象的引用,因此这Thread.currentThread()
将起作用。
出于同样的原因,您不能只将对 JFrame 的引用设置为 null 以使窗口神奇地消失。JVM 具有对线程的引用,因此即使您忘记了线程,JVM 也不会。您需要正确终止线程,最好是通过结束其主要功能。
您只是将变量的值设置为 null。
所以,问题是任何线程是否有效地引用了该Thread
对象。考虑新线程本身......它可以很容易地包括
System.out.println(Thread.currentThread());
如果Thread
对象已被垃圾回收,你会期望它做什么?
对象只是在不再存在对它们的实时引用之后的某个时候才被垃圾收集。任何活动线程都有对其自身的引用。
坦率地说,如果您必须确保确实保留了刚刚启动的线程的引用,以防止它被突然停止,那将是一件痛苦的事情。