GC可以在这里收集我的变量,即使我在另一个线程中使用它吗?

时间:2011-12-13 17:06:20

标签: java multithreading nested-class

假设我创建了这个Test类的实例,它使用嵌套类启动一个新的Thread:

public class Test
{
    private String _str;

    public Test()
    {
        _str = "Hello world !";
        new TestThread().start(); // Start a background thread
    }


    private class TestThread extends Thread
    {
        public void run()
        {
            while (true)
            {
                System.out.println(_str);
                Thread.sleep(1000);
            }
        }
    }
}

如果删除对Test实例的任何强引用,会发生什么?后台线程仍然存在,并将继续打印_str变量,但我担心GC可以随时收集它。

当然我可以创建引用的本地副本(使用构造函数:public TestThread(String str)并将其存储在局部变量中)但我不知道这是否有必要。

2 个答案:

答案 0 :(得分:5)

TestThread本身 强烈引用Test,因此只要它不可收集,Test的实例将无法收集。由于它是一个正在运行的线程,TestThread的实例显然无法收集。

当您创建非静态内部类(TestThread)时,该类的每个实例都有一个隐式引用到其封闭类的实例(Test)。

请参阅Nested Classes Java Tutorial的内部类。

您不必“害怕”GC可能会做什么。它不会收集您可能引用的对象,除非您不想使用弱引用。

答案 1 :(得分:1)

您不必担心gc,但无法保证_str的内存可见性。

您需要_str为final或volatile,以确保TestThread看到正确的值。你还需要在构造函数之后启动线程。当前代码允许在构造函数完成之前从另一个线程访问this指针,这使得final的保证无效。

将TestThread中的_str副本(如您所述)存储为最终变量,然后使TestThread成为静态类将解决所有这些问题。