我想在Java中实现Thread Safe Lazily Loaded Singleton。
这是一个好的设计吗?
public final class ThreadSafeLazySynchronizedSingleton {
private ThreadSafeLazySynchronizedSingleton(){}
private static ThreadSafeLazySynchronizedSingleton instance;
public static ThreadSafeLazySynchronizedSingleton getSynchronizedInstance(){
synchronized(ThreadSafeLazySynchronizedSingleton.class){
if (instance==null){
instance = new ThreadSafeLazySynchronizedSingleton();
}
return instance;
}
}
}
我还想创建一个无锁版本,以便在一个线程比其他线程多次访问Singleton的场景中使用,我将如何使用Java中的原子对象,即AtomicBoolean或AtomicReference等来实现这一点。你能提供一个代码示例吗?
答案 0 :(得分:3)
更好的设计是
public final class ThreadSafeLazySynchronizedSingleton {
private ThreadSafeLazySynchronizedSingleton(){}
private static volatile ThreadSafeLazySynchronizedSingleton instance;
public static ThreadSafeLazySynchronizedSingleton getSynchronizedInstance(){
if (instance==null)
synchronized(ThreadSafeLazySynchronizedSingleton.class){
if (instance==null){
instance = new ThreadSafeLazySynchronizedSingleton();
}
return instance;
}
}
}
然而,最好的设计恕我直言
public enum ThreadSafeLazySynchronizedSingleton {
INSTANCE;
}
答案 1 :(得分:1)
在Java中实现Singleton设计模式的推荐方法是使用Enum方法。 Enum方法非常简单,并且隐含了线程安全性。
public enum EnumTest {
INSTANCE;
// Test code
public static void main(String[] args) {
// First thread
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
EnumTest obj = EnumTest.INSTANCE;
}
});
t1.start();
// Second thread
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
EnumTest obj = EnumTest.INSTANCE;
}
});
t2.start();
}
}
很好的教程here。
答案 2 :(得分:0)
最简单的事情可能就像你需要它一样懒惰:
private static ThreadSafeLazySynchronizedSingleton instance
= new ThreadSafeLazySynchronizedSingleton();
public static ThreadSafeLazySynchronizedSingleton instance() {
return instance;
}
是的,一旦加载了类,就会创建instance
。但是在使用它之前,这个类不会被加载,到那时你可能需要得到实例。
如果ThreadSafeLazySynchronizedSingleton
类还有不使用instance
的静态辅助方法,那么这个不会像你需要的那样懒惰的唯一一次,但这表明他们与班上的其他人没什么关系,可能应该搬到他们自己的班级。
很多人也使用单值enum
作为单身人士。我个人觉得它很难看,但它确实有一些优点(为你处理私有构造函数和instance
,即使你的类是可序列化的,也会强制执行单例,否则这不是一件容易的事。)
答案 3 :(得分:0)
如果你想要一个真正的无锁实现,它需要一些旋转。否则@yshavit或@Peter Lawrey是最好的答案。
免费锁定:
private static final AtomicBoolean created = new AtomicBoolean(false);
private static volatile LazySingleton instance = null;
public static ThreadSafeLazySynchronizedSingleton getIntsance(){
if(instance != null) return instance.get();
if(created.compareAndSet(false, true)){
//only one thread can try and create
instance = new LazySingleton();
} else {
//other thread is creating, spin until ready
while(instance == null);
}
return instance;
}