Java线程垃圾收集与否
这个问题被张贴在一些网站上。 我没有find正确的答案,所以我在这里再次发布。
public class TestThread { public static void main(String[] s) { // anonymous class extends Thread Thread t = new Thread() { public void run() { // infinite loop while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { } // as long as this line printed out, you know it is alive. System.out.println("thread is running..."); } } }; t.start(); // Line A t = null; // Line B // no more references for Thread t // another infinite loop while (true) { try { Thread.sleep(3000); } catch (InterruptedException e) { } System.gc(); System.out.println("Executed System.gc()"); } // The program will run forever until you use ^C to stop it } }
我的查询不是关于停止线程。 让我重述一下我的问题。 行A(见上面的代码)启动一个新的线程; 而B行使线程引用为空。 所以,JVM现在有一个线程对象(它处于运行状态),其中没有引用存在(如线B中的t = null)。 所以我的问题是,为什么这个线程(主线程中没有引用)继续运行,直到主线程运行。 根据我的理解,线程对象应该在B行后面被垃圾回收。我试图运行这个代码5分钟以上,请求Java运行时运行GC,但是线程不停止。
希望这个代码和问题都清楚。
正在运行的线程被认为是所谓的垃圾收集根,并且是阻止垃圾收集的东西之一。 当垃圾收集器确定您的对象是否可访问时 ,它总是这样做,使用垃圾收集器根作为参考点。
考虑一下,为什么你的主线程不被垃圾收集,也没有人引用那个。
正如所解释的,根据定义,正在运行的线程对GC不起作用。 GC开始工作,扫描被认为总是可以到达的“根” 根包括全局variables(Java-talk中的“静态字段”)和所有正在运行的线程的堆栈(可以想象,正在运行的线程的堆栈引用相应的Thread
实例)。
但是,您可以将线程设置为“守护程序”线程(请参阅Thread.setDaemon(boolean)
)。 守护程序线程不会比非守护程序线程更垃圾收集,但当所有正在运行的线程都是守护进程时,JVM将退出。 一种想象的方式是每个线程在终止时检查是否存在一些非守护进程的运行线程; 如果不是,终止线程会强制执行一个System.exit()
调用,该调用将退出JVM(closures正在运行的守护进程线程)。 这不是GC相关的问题; 在某种程度上,线程是手动分配的。 但是,这是JVM如何容忍半stream氓线程。 这通常用于Timer
实例。
JVM具有对所有正在运行的线程的引用。
没有任何线程(或者它指向的东西)在它仍然在运行时将被垃圾收集。
线程不是垃圾收集,因为有线程的引用,你看不到。 例如,在运行系统中有引用。
线程创build时,它被添加到当前线程组。 您可以获取当前线程组中的线程列表,这是另一种获取对它的引用的方法。