java中延迟线程安全单例实例化的模式

Igo*_*hin 16 java singleton instantiation thread-safety lazy-evaluation

懒惰的线程安全单例实例对每个编码器来说都不容易理解,所以我想在我们的企业框架中创建一个可以完成这项工作的类.

你怎么看待这件事?你觉得它有什么坏处吗?在Apache Commons中有类似的东西吗?我怎样才能让它变得更好?

Supplier.java

public interface Supplier<T> {
    public T get();
}
Run Code Online (Sandbox Code Playgroud)

LazyThreadSafeInstantiator.java

public class LazyThreadSafeInstantiator<T> implements Supplier<T> {
    private final Supplier<T> instanceSupplier;

    private volatile T obj;

    public LazyThreadSafeInstantiator(Supplier<T> instanceSupplier) {
        this.instanceSupplier = instanceSupplier;
    }

    @Override
    // http://en.wikipedia.org/wiki/Double-checked_locking
    public T get() {
        T result = obj;  // Wikipedia: Note the usage of the local variable result which seems unnecessary. For some versions of the Java VM, it will make the code 25% faster and for others, it won't hurt.
        if (result == null) {
            synchronized(this) {
                result = obj;
                if (result == null) {
                    result = instanceSupplier.get();
                    obj = result;
                }
            }
        }
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例:

public class Singleton1 {
    private static final Supplier<Singleton1> instanceHolder =
        new LazyThreadSafeInstantiator<Singleton1>(new Supplier<Singleton1>() {
            @Override
            public Singleton1 get() {
                return new Singleton1();
            }
        });

    public Singleton1 instance() {
        return instanceHolder.get();
    }

    private Singleton1() {
        System.out.println("Singleton1 instantiated");
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢

Mic*_*rdt 55

懒惰的线程安全单例实例对每个编码器来说都不容易理解

不,它实际上非常非常容易:

public class Singleton{
    private final static Singleton instance = new Singleton();
    private Singleton(){ ... }
    public static Singleton getInstance(){ return instance; }
}
Run Code Online (Sandbox Code Playgroud)

更好的是,让它成为一个枚举:

public enum Singleton{
    INSTANCE;
    private Singleton(){ ... }
}
Run Code Online (Sandbox Code Playgroud)

它是线程安全的,它是懒惰的(初始化发生在类加载时,Java不会加载类,直到它们被首次引用).

事实上,99%的时候你根本不需要延迟加载.剩下的1%,在0.9%以上,完全是懒惰的.

您是否运行过探查器并确定您的应用程序属于真正需要首先访问延迟加载的0.01%?不这么认为.那你为什么要浪费时间来编造这些Rube Goldbergesque代码可恶来解决一个不存在的问题呢?

  • @savinos:因为它使自动线程安全和可序列化,同时保留单例属性.特别是后者需要大量工作才能手动完成. (3认同)

Vin*_*lds 5

对于比问题中提供的更具可读性(在我看来)的版本,可以参考Bill Pugh介绍的Initialization on Demand Holder惯用法.考虑到Java 5内存模型,它不仅是线程安全的,单例也被懒惰地初始化.