如何实现线程安全的惰性初始化?

新手上路,请多包涵

实现 线程安全 延迟初始化的一些推荐方法是什么?例如,

 // Not thread-safe
public Foo getInstance(){
    if(INSTANCE == null){
        INSTANCE = new Foo();
    }

    return INSTANCE;
}

原文由 mre 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 622
2 个回答

对于单例,有一个优雅的解决方案,将任务委托给 JVM 代码进行静态初始化。

 public class Something {
    private Something() {
    }

    private static class LazyHolder {
            public static final Something INSTANCE = new Something();
    }

    public static Something getInstance() {
            return LazyHolder.INSTANCE;
    }
}

http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom

以及 Crazy Bob Lee 的这篇博文

http://blog.crazybob.org/2007/01/lazy-loading-singletons.html

原文由 Peter Tillemans 发布,翻译遵循 CC BY-SA 3.0 许可协议

如果您使用的是 Apache Commons Lang ,那么您可以使用 ConcurrentInitializer 的变体之一,例如 LazyInitializer

例子:

 ConcurrentInitializer<Foo> lazyInitializer = new LazyInitializer<Foo>() {

        @Override
        protected Foo initialize() throws ConcurrentException {
            return new Foo();
        }
    };

您现在可以安全地获取 Foo(仅初始化一次):

 Foo instance = lazyInitializer.get();

如果您使用的是 Google 的 Guava

 Supplier<Foo> fooSupplier = Suppliers.memoize(new Supplier<Foo>() {
    public Foo get() {
        return new Foo();
    }
});

然后通过 Foo f = fooSupplier.get(); 调用它

来自 Suppliers.memoize javadoc

返回一个供应商,它缓存在第一次调用 get() 期间检索到的实例,并在后续调用 get() 时返回该值。返回的供应商是 线程安全的。委托的 get() 方法将 最多被调用一次。如果 delegate 是之前调用 memoize 创建的实例,则直接返回。

原文由 Kenston Choi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题