Java 中的这种弱单例实现是线程安全的(和 GC 安全的)吗?
Is this weak singleton implementation in Java thread-safe (and GC-safe)?
我想达到以下效果:
- 我只希望周围有一个 class 实例。当有多个对 class 的引用时,我希望它们都引用同一个实例。
- 除非需要,否则我不希望实例出现。具体来说,我希望垃圾收集器能够在不使用时回收实例,并在下次请求实例时重新创建它。
- 多个线程可能会请求一个实例,因此操作必须是线程安全的。
这是我想出的代码:
public final class MyClass {
private static WeakReference<MyClass> instance;
public static synchronized MyClass getInstance() {
if ((instance == null) || (instance.get() == null)) {
instance = new WeakReference<MyClass>(new MyClass());
}
// TODO what if GC strikes here?
return instance.get();
}
}
设计选择是:
- 惰性初始化,因此除非需要,否则不会创建实例
- class 保留对实例的 WeakReference,以便实例在不再使用时可以被垃圾回收。
getInstance()
方法是synchronized
(到MyClass
)所以一次只能由一个线程执行。
问题:
- 此设计是否会按照我的预期运行并产生预期的结果?
- 我是否必须担心
getInstance()
被评论所在的垃圾收集器打断(这意味着垃圾收集器会回收我正要 return 的实例)?如果是这样,我该如何解决?
将 MyClass
的本地副本保存在变量中,而不是仅将引用的唯一副本提供给 WeakRefrence
的构造函数。这将防止 GC 在 new WeakReference<MyClass>
调用和函数返回之间收集 instance
。
public final class MyClass {
private static WeakReference<MyClass> instance;
public static synchronized MyClass getInstance() {
MyClass classInstance = null;
if (instance != null) {
classInstance = instance.get();
if(classInstance != null)
{
return classInstance;
}
}
classInstance = new MyClass();
instance = new WeakReference<MyClass>(classInstance);
//This is now a strong reference and can't be GC'ed between the previous line and this one.
return classInstance;
}
}
我想达到以下效果:
- 我只希望周围有一个 class 实例。当有多个对 class 的引用时,我希望它们都引用同一个实例。
- 除非需要,否则我不希望实例出现。具体来说,我希望垃圾收集器能够在不使用时回收实例,并在下次请求实例时重新创建它。
- 多个线程可能会请求一个实例,因此操作必须是线程安全的。
这是我想出的代码:
public final class MyClass {
private static WeakReference<MyClass> instance;
public static synchronized MyClass getInstance() {
if ((instance == null) || (instance.get() == null)) {
instance = new WeakReference<MyClass>(new MyClass());
}
// TODO what if GC strikes here?
return instance.get();
}
}
设计选择是:
- 惰性初始化,因此除非需要,否则不会创建实例
- class 保留对实例的 WeakReference,以便实例在不再使用时可以被垃圾回收。
getInstance()
方法是synchronized
(到MyClass
)所以一次只能由一个线程执行。
问题:
- 此设计是否会按照我的预期运行并产生预期的结果?
- 我是否必须担心
getInstance()
被评论所在的垃圾收集器打断(这意味着垃圾收集器会回收我正要 return 的实例)?如果是这样,我该如何解决?
将 MyClass
的本地副本保存在变量中,而不是仅将引用的唯一副本提供给 WeakRefrence
的构造函数。这将防止 GC 在 new WeakReference<MyClass>
调用和函数返回之间收集 instance
。
public final class MyClass {
private static WeakReference<MyClass> instance;
public static synchronized MyClass getInstance() {
MyClass classInstance = null;
if (instance != null) {
classInstance = instance.get();
if(classInstance != null)
{
return classInstance;
}
}
classInstance = new MyClass();
instance = new WeakReference<MyClass>(classInstance);
//This is now a strong reference and can't be GC'ed between the previous line and this one.
return classInstance;
}
}