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
传递给构造函数调用。请看一个工作示例。