这是在Java线程安全(和GC安全)中的弱单独实现吗?

use*_*408 1 java singleton multithreading garbage-collection weak-references

我想达到以下结果:

  • 我想只有一个类的实例.当有多个类的引用时,我希望它们都引用同一个实例.
  • 除非需要,否则我不想要实例.具体来说,我希望垃圾收集器能够在不使用时回收实例,并在下次请求实例时重新创建它.
  • 多个线程可以请求实例,因此操作必须是线程安全的.

这是我提出的代码:

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

设计选择包括:

  • 延迟初始化,因此除非需要,否则不会创建实例
  • 该类将WeakReference保留给实例,以便实例在不再使用时可以进行垃圾回收.
  • getInstance()方法是synchronized(至MyClass),以便它一次只能由一个线程执行.

问题:

  • 这个设计是否会像我期望的那样表现并产生预期的结果?
  • 我是否必须担心getInstance()被评论所在的垃圾收集器打断(意味着垃圾收集器会收回我刚要返回的实例)?如果是这样,我该如何解决呢?

Sco*_*ain 6

保留MyClass变量的本地副本,而不是仅将您的引用副本提供给构造函数WeakRefrence.这将阻止GC instancenew WeakReference<MyClass>调用和返回函数之间进行收集.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)