是否收集了Java Thread Garbage

Ash*_*ish 84 java multithreading garbage-collection

这个问题发布在某个网站上.我没有在那里找到正确的答案,所以我再次在这里发布.

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
    }
}
Run Code Online (Sandbox Code Playgroud)

我的查询不是关于停止线程.让我重新解释一下我的问题.A行(见上面的代码)启动一个新线程; 和B行使线程引用为null.因此,JVM现在有一个没有引用的线程对象(处于运行状态)(在线B中为t = null).所以我的问题是,为什么这个线程(主线程中没有引用)继续运行直到主线程运行.根据我的理解,线程对象应该在B行后进行垃圾收集.我尝试运行此代码5分钟以上,请求Java运行时运行GC,但线程不会停止.

希望这次代码和问题都清楚.

fal*_*tro 121

正在运行的线程被认为是所谓的垃圾收集根,并且是阻止垃圾收集的东西之一.当垃圾收集器确定您的对象是否" 可访问 "时,它始终使用垃圾收集器根集合作为参考点.

考虑一下,为什么你的主线程没有被垃圾收集,也没有人引用那个.

  • 这个答案,就目前而言,提出了一个问题,即线程是否可以完全根据GC(终止后).由于此问题被标记为[this one](http://stackoverflow.com/questions/10380327/java-threads-and-garbage-collector)的副本,因此应该提到线程将不再标记为"垃圾收集根"在它们终止后,因此,它们可以在GC中访问. (13认同)
  • 最后一句是透彻的:"为什么你的主线不是垃圾...". (12认同)

Tho*_*nin 22

如上所述,根据定义,运行线程对GC免疫.GC通过扫描"根"开始工作,这些"根"被认为总是可以到达的; 根包括全局变量(Java-talk中的"静态字段")和所有正在运行的线程的堆栈(可以想象正在运行的线程的堆栈引用相应的Thread实例).

但是,您可以将线程设置为"守护程序"线程(请参阅参考资料Thread.setDaemon(boolean)).守护程序线程不会比非守护程序线程更多地进行垃圾收集,但是当所有正在运行的线程都是守护程序时,JVM会退出.想象一下的一种方法是每个线程在终止时检查是否还有一些非守护进程正在运行的线程; 如果没有,终止线程强制System.exit()调用,该调用退出JVM(终止正在运行的守护程序线程).这不是与GC相关的问题; 在某种程度上,线程是手动分配的.但是,这就是JVM可以容忍半流氓线程的方式.这通常用于Timer实例.


Thi*_*ilo 18

JVM引用了所有正在运行的线程.

没有线程(或它引用的东西)在它仍在运行时将被垃圾收集.


vy3*_*y32 12

线程不是垃圾收集,因为有对您无法看到的线程的引用.例如,运行时系统中有引用.

创建线程时,它将添加到当前线程组.您可以在当前线程组中获取线程列表,这是另一种获取对它的引用的方法.