Java中的弱单例实现是线程安全(和GC安全)的吗?
我希望取得以下成果:Java中的弱单例实现是线程安全(和GC安全)的吗?,java,multithreading,garbage-collection,singleton,weak-references,Java,Multithreading,Garbage Collection,Singleton,Weak References,我希望取得以下成果: 我只希望有一个类的实例。当类有多个引用时,我希望它们都引用同一个实例 除非需要,否则我不希望实例出现。具体来说,我希望垃圾收集器能够在不使用时回收实例,并在下次请求实例时重新创建它 多个线程可能会请求一个实例,因此操作必须是线程安全的 这是我想出的代码: public final class MyClass { private static WeakReference<MyClass> instance; public static sync
- 我只希望有一个类的实例。当类有多个引用时,我希望它们都引用同一个实例
- 除非需要,否则我不希望实例出现。具体来说,我希望垃圾收集器能够在不使用时回收实例,并在下次请求实例时重新创建它
- 多个线程可能会请求一个实例,因此操作必须是线程安全的
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();
}
}
公共最终类MyClass{
私有静态WeakReference实例;
公共静态同步MyClass getInstance(){
if((instance==null)| |(instance.get()==null)){
instance=newweakreference(newmyclass());
}
//TODO如果GC攻击这里怎么办?
返回instance.get();
}
}
设计选择包括:
- 延迟初始化,因此除非需要,否则不会创建实例
- 该类保留对实例的WeakReference,以便在不再使用该实例时可以对其进行垃圾收集
方法是getInstance()
(到synchronized
),因此一次只能由一个线程执行MyClass
- 这个设计会像我期望的那样运行并产生预期的结果吗
- 我是否需要担心
被注释所在的垃圾收集器打断(意味着垃圾收集器将回收我正要返回的实例)?如果是这样,我如何解决它getInstance()
MyClass
的本地副本,而不是将引用的唯一副本提供给WeakRefrence
的构造函数。这将防止GC在新WeakReference
调用和函数返回之间收集实例
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;
}
}
公共最终类MyClass{
私有静态WeakReference实例;
公共静态同步MyClass getInstance(){
MyClass classInstance=null;
if(实例!=null){
classInstance=instance.get();
if(classInstance!=null)
{
返回类实例;
}
}
classInstance=新的MyClass();
实例=新的WeakReference(classInstance);
//这现在是一个强引用,不能在前一行和这一行之间进行GC'ed。
返回类实例;
}
}
在变量中保存MyClass
的本地副本,而不是将引用的唯一副本提供给WeakRefrence
的构造函数。这将防止GC在新WeakReference
调用和函数返回之间收集实例
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;
}
}
公共最终类MyClass{
私有静态WeakReference实例;
公共静态同步MyClass getInstance(){
MyClass classInstance=null;
if(实例!=null){
classInstance=instance.get();
if(classInstance!=null)
{
返回类实例;
}
}
classInstance=新的MyClass();
实例=新的WeakReference(classInstance);
//这现在是一个强引用,不能在前一行和这一行之间进行GC'ed。
返回类实例;
}
}
您可以在方法getInstance()
的开头有一些MyClass-actualInstance
,设置actualInstance=new-MyClass()
并将actualInstance
传递给构造函数调用,而不是将新对象传递给构造函数。请看一个工作示例。您可以在方法getInstance()
的开始处使用一些MyClass-instance
,而不是将新对象传递给构造函数,设置instance=new-MyClass()
并将instance
传递给构造函数调用。请看一个工作示例。