如何实现线程安全的惰性初始化?
2022-08-31 14:51:00
有哪些推荐的方法来实现线程安全的延迟初始化?例如
// Not thread-safe
public Foo getInstance(){
if(INSTANCE == null){
INSTANCE = new Foo();
}
return INSTANCE;
}
有哪些推荐的方法来实现线程安全的延迟初始化?例如
// Not thread-safe
public Foo getInstance(){
if(INSTANCE == null){
INSTANCE = new Foo();
}
return INSTANCE;
}
对于单例,有一个优雅的解决方案,通过将任务委托给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
和这篇疯狂的鲍勃李的博客文章
http://blog.crazybob.org/2007/01/lazy-loading-singletons.html
如果您使用的是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();
如果您使用的是谷歌的番石榴:
Supplier<Foo> fooSupplier = Suppliers.memoize(new Supplier<Foo>() {
public Foo get() {
return new Foo();
}
});
然后调用它Foo f = fooSupplier.get();
From Suppliers.memoize javadoc:
返回一个供应商,该供应商缓存在第一次调用 get() 期间检索到的实例,并在后续调用 get() 时返回该值。返回的供应商是线程安全的。委托的 get() 方法最多调用一次。如果委托是由先前调用 memoize 创建的实例,则直接返回该实例。