【问题标题】:Can the GC collect my variable here, even if I use it in another thread?即使我在另一个线程中使用它,GC 可以在这里收集我的变量吗?
【发布时间】:2011-12-13 17:06:19
【问题描述】:

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

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) 并将其存储在本地变量中)但我想知道这是否有必要。

【问题讨论】:

    标签: java multithreading nested-class


    【解决方案1】:

    TestThread 本身Test 的强引用,所以只要它不是可收集的,Test 的实例就不会是可收集的。由于它是一个正在运行的线程,TestThread 的实例显然不可用于收集。

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

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

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

    【讨论】:

      【解决方案2】:

      你不必担心 gc,但不能保证 _str 的内存可见性。

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

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

      【讨论】:

        猜你喜欢
        • 2015-09-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-12
        • 2015-03-16
        相关资源
        最近更新 更多