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

时间:2017-05-27 15:24:12

标签: java multithreading garbage-collection singleton 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();
    }
}

设计选择是:

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

问题:

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

1 个答案:

答案 0 :(得分:6)

在变量中保留MyClass的本地副本,而不是仅将您的引用副本提供给WeakRefrence的构造函数。这将阻止GC在instance调用和返回函数之间收集new 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;
    }
}