这是Java中线程安全的Lazily Loaded Singleton的一个很好的实现吗?

时间:2014-06-26 15:29:35

标签: java multithreading singleton lazy-initialization

我想在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等来实现这一点。你能提供一个代码示例吗?

4 个答案:

答案 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;
}