繁体   English   中英

单例实现示例

[英]Singleton Implementation example

我正在尝试找到自己的Java Singleton实现方式。 代码如下:

public class Singleton{
   private volatile static Singleton _instance = null;
   private Singleton(){}
   public static Singleton getInstance(){
      if (_instance == null)
         Object obj = new Object();
         synchronized(obj){
            if (_instance == null)
               _instance = new Singleton();
         }
      return _instance;
}

此代码有效吗? 如果不起作用,该如何解决?

否-您的代码无效,因为锁对象是局部变量,因此每个线程都不同。

您正在尝试实现惰性初始化模式-首次使用实例时在其中创建实例。

但是有一个简单的技巧,可以让你编写一个线程安全的实现, 不需要同步! 它称为“ 按需初始化持有人”习惯用法 ,它看起来像这样:

public class Singleton {
    private static class Holder {
        static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }

    private Singleton() {
    }

    // rest of class omitted
}

此代码在第一次调用getInstance()初始化实例,并且重要的是,由于类加载器的约定,不需要同步:

  • 类加载器在第一次访问类时加载类(在这种情况下, Holder的唯一访问是在getInstance()`方法内)
  • 当加载一个类时,并且在任何人都可以使用它之前,保证所有静态初始化程序都将被执行(这是Holder的静态块触发时)
  • 类加载器内置了自己的同步功能,可以确保上述两点是线程安全的

每当需要懒惰初始化时,我都会使用这巧妙的小技巧。 您还可以获得final实例的奖励,甚至认为它是惰性创建的。 还要注意代码是多么干净和简单。

不懒惰的单身人士的棘手且非常简单的实现:

public enum TickySingleton {

    INSTANCE;

    public void doSomething() { ... }
    public Object returnSomething() { ... }
}

}

不是每个人都会喜欢这样。 ;)

如果您的同步对象是final static会更好。 否则,每个可能的并发线程将创建自己的同步对象并锁定不同的对象。 他们不会互相等待。

public class Singleton{

   private final static Object obj = new Object();
   private volatile static Singleton _instance = null;

   private Singleton(){}

   public static Singleton getInstance(){
     if (_instance == null)
        synchronized(obj){
           if (_instance == null)
              _instance = new Singleton();
         }
      }
      return _instance;
   }

当你写:

Object obj = new Object();
synchronized(obj){}

JVM可以证明没有两个线程可以获取该锁(因为它是局部变量),因此可以完全删除同步。

关于单例的一些评论:

不,这是不正确的,您应该在Singleton.class上进行同步

class Singleton {
       private volatile static Singleton _instance;
       private Singleton(){}
       public static Singleton getInstance(){
          if (_instance == null)
             synchronized(Singleton.class){
                if (_instance == null)
                   _instance = new Singleton();
             }
          return _instance;
    }
}

这是一种已知的双重检查锁定模式,有关详细信息,请参见http://www.ibm.com/developerworks/java/library/j-dcl/index.html

请注意,由于此类中只有一个方法,因此以下内容可达到相同目的,而无需任何双重检查的技巧,而且它也是懒惰的

class Singleton {
       private static Singleton _instance = new Singleton();
       private Singleton(){}
       public static Singleton getInstance(){
          return _instance;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM