这是Java中线程安全的延迟加载单例的一个很好的实现吗?



我想在Java中实现线程安全的惰性加载单例。

这个设计好吗?

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

一个更好的设计是

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

在Java中实现单例设计模式的推荐方法是使用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();
   }
 }

最简单的东西可能会像你需要的那样懒惰:

private static ThreadSafeLazySynchronizedSingleton instance
    = new ThreadSafeLazySynchronizedSingleton();
public static ThreadSafeLazySynchronizedSingleton instance() {
    return instance;
}

True, instance将在类加载后立即创建。但是类在被使用之前是不会被加载的,这时你可能需要获取实例。

如果ThreadSafeLazySynchronizedSingleton类也有不使用instance的静态助手方法,那么这不会像您需要的那样懒惰,但这表明它们与类的其余部分没有太多关系,可能应该移动到自己的类中。

很多人也将单值enum用于单例。我个人觉得它很丑,但它确实有一些优点(为您处理私有构造函数和instance,并且即使您的类是可序列化的,也强制执行单例性,否则这不是微不足道的)。

如果你想要一个真正的无锁实现,它将需要一些旋转。否则,@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;
}

最新更新