假设我创建了这个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)
并将其存储在局部变量中)但我不知道这是否有必要。
答案 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成为静态类将解决所有这些问题。