Java线程和垃圾收集

时间:2014-08-22 15:14:05

标签: java multithreading garbage-collection

我已经在无数地方读过,运行线程是垃圾收集根(即它们驻留在堆栈上,GC识别它们并跟踪它们以确定它们内部的对象是否仍然可以访问)。此外,GC根目录永远不会被垃圾收集。

我的困惑在于:如果从线程内部分配的对象永远不会被垃圾收集,直到线程被停止,那么如何在单线程程序中收集任何垃圾,其中唯一的线程是主线程?

显然我在这里遗漏了一些东西。

2 个答案:

答案 0 :(得分:1)

对象在堆中,无论哪个线程创建它们。

可以通过引用访问对象。其中一些引用可以在一个或多个线程的调用堆栈上。

当没有更多对它的引用时,可以收集一个对象,无论分配线程是否仍在运行。

例如,下面的线程重复分配新的StringBuilder对象。在调用foo()期间,线程在其调用堆栈上引用了StringBuilder对象。当foo()返回时,没有对StringBuilder对象的进一步引用。因此,该对象不再可访问,并且符合条件用于垃圾回收。

Thread thread = new Thread( new Runnable() {
    @Override
    public void run() {
        while ( true ) {
            foo();
        }
    }

    public void foo() {
        StringBuilder strBuilder = new StringBuilder("This new object is allocated on the heap.");
        System.out.println( strBuilder );
    }
});

thread.run();

答案 1 :(得分:1)

首先,线程(堆栈)只有GC根目录才有效。当线程终止时,它不再是GC根目录。

  

我的困惑在于:如果从线程内部分配的对象永远不会被垃圾收集,直到线程被停止,那么如何在单线程程序中收集任何垃圾,其中唯一的线程是主线程?

你的前提不正确。

哪个线程分配对象并不重要。重要的是您的线程分配的对象是否仍然可以访问。如果它变得无法访问(例如,如果你没有将对象的引用放入局部变量中)......那么就可以收集它。