实现线程安全的延迟初始化的推荐方法是什么?例如,
// Not thread-safe
public Foo getInstance(){
if(INSTANCE == null){
INSTANCE = new Foo();
}
return INSTANCE;
}发布于 2011-11-28 15:06:11
对于单例,有一个优雅的解决方案,将任务委托给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://blog.crazybob.org/2007/01/lazy-loading-singletons.html
发布于 2014-04-22 09:56:12
如果您使用的是Apache ,那么您可以使用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();调用它
来自Suppliers.memoize javadoc
返回一个提供者,它缓存在第一次调用get()期间检索的实例,并在随后调用get()时返回该值。返回的供应商是thread-safe.委托的get()方法最多只调用一次()。如果委托是以前调用回忆录所创建的实例,则直接返回它。
发布于 2015-05-14 20:57:12
通过使用AtomicReference作为实例持有人,可以以无锁的方式完成此操作:
// in class declaration
private AtomicReference<Foo> instance = new AtomicReference<>(null);
public Foo getInstance() {
Foo foo = instance.get();
if (foo == null) {
foo = new Foo(); // create and initialize actual instance
if (instance.compareAndSet(null, foo)) // CAS succeeded
return foo;
else // CAS failed: other thread set an object
return instance.get();
} else {
return foo;
}
}这里的主要缺点是多个线程可以同时实例化两个或多个Foo对象,并且只有一个是幸运的,因此如果实例化需要I/O或另一个共享资源,则此方法可能不适合。
另一方面,这种方法是无锁和无等待:如果第一个进入该方法的线程被卡住,它不会影响其他线程的执行。
https://stackoverflow.com/questions/8297705
复制相似问题