Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中的这个单例类可以接受吗?_Java_Design Patterns_Singleton - Fatal编程技术网

Java中的这个单例类可以接受吗?

Java中的这个单例类可以接受吗?,java,design-patterns,singleton,Java,Design Patterns,Singleton,我使用了已出版的关于单例创建的教程中的概念,但希望得到一些反馈。有没有更好的方法 public class MyDoubleLockSingleton { private volatile static Object _mySingleton; //private constructor private MyDoubleLockSingleton() { if (_mySingleton == null) { MyDoubleLockS

我使用了已出版的关于单例创建的教程中的概念,但希望得到一些反馈。有没有更好的方法

public class MyDoubleLockSingleton {

    private volatile static Object _mySingleton;

//private constructor
    private MyDoubleLockSingleton() {
        if (_mySingleton == null) {
            MyDoubleLockSingleton.getSingleton();
        }
    }

//  double lock singleton approach
    public static Object getSingleton() {
        synchronized (MyDoubleLockSingleton.class) {
            if (_mySingleton == null) {
            _mySingleton = new Object();
        }
        return (Object)_mySingleton;
        }
    }
}

除了像Vince提到的那样进行同步之外,在get singleton中返回对象也是很好的。通常在单例中,方法称为instance或getInstance。移除构造函数的主体。可以使用单例模式,但若可以,请尽量避免使用单例模式,否则在应用程序只有一个线程时,请尽可能快地初始化它。一般规则-单身汉越少越好。参见本文

从文章看区别

class SomeClass {
  private Resource resource = null;
  public Resource getResource() {
    if (resource == null) {
      synchronized {
        if (resource == null) 
          resource = new Resource();
      }
    }
    return resource;
  }
}

class A {
  static private A a = null;
  public Resource instance() {
    if ( a == null ) {
      synchronized {
        if (a == null ) 
           a= new A();
      }
    }
    return a;
  }
}

实际上,有一种首选方法,也是最容易实现的方法枚举

  • 它们保证在JVM中只有一个实例
  • 它们可以安全地序列化
  • 它们是线程安全的

    • 它看起来更像这样:

      public class MyDoubleLockSingleton {
      
          private static final Object _lock = new Object(); // synchronize on this instead of MyDoubleLockSingleton.class
          private volatile static MyDoubleLockSingleton _mySingleton;
      
          //private constructor
          private MyDoubleLockSingleton() {
              // perform expensive initialization here.
          }
      
          //  double lock singleton approach
          public static MyDoubleLockSingleton getSingleton() {
              if (_mySingleton == null) {
                  synchronized (_lock) {
                      if (_mySingleton == null) {
                          _mySingleton = new Object();
                      }
                  }
              }
              return _mySingleton;
          }
      }
      
      public class MyDoubleLockSingleton {
      
          private static final MyDoubleLockSingleton _mySingleton = new MyDoubleLockSingleton();
      
          //private constructor
          private MyDoubleLockSingleton() {
              // perform initialization here.
          }
      
          //  double lock singleton approach
          public static Object getSingleton() {
              return _mySingleton;
          }
      }
      
      • 私有构造函数是执行昂贵初始化的地方
      • 您最好在私人成员上同步
      • 您可能希望在同步块之外添加空检查,以提高性能。否则,这种模式就没有什么意义了
      现在,如果您的私有构造函数的代码没有那么昂贵,那么尝试执行延迟初始化就没有任何意义了。在这种情况下,请保持非常简单,如下所示:

      public class MyDoubleLockSingleton {
      
          private static final Object _lock = new Object(); // synchronize on this instead of MyDoubleLockSingleton.class
          private volatile static MyDoubleLockSingleton _mySingleton;
      
          //private constructor
          private MyDoubleLockSingleton() {
              // perform expensive initialization here.
          }
      
          //  double lock singleton approach
          public static MyDoubleLockSingleton getSingleton() {
              if (_mySingleton == null) {
                  synchronized (_lock) {
                      if (_mySingleton == null) {
                          _mySingleton = new Object();
                      }
                  }
              }
              return _mySingleton;
          }
      }
      
      public class MyDoubleLockSingleton {
      
          private static final MyDoubleLockSingleton _mySingleton = new MyDoubleLockSingleton();
      
          //private constructor
          private MyDoubleLockSingleton() {
              // perform initialization here.
          }
      
          //  double lock singleton approach
          public static Object getSingleton() {
              return _mySingleton;
          }
      }
      

      您最大的缺陷是在每次调用
      getSingleton()
      时同步

      “双重检查”锁定的思想是首先执行非同步检查。这适用于单例已初始化的情况如果单例已经存在,则没有理由进行同步

      如果在执行非同步检查时单例为
      null
      ,则同步:

      public Singleton getSingleton() {
          if(singleton == null) {
              synchronized(lock) {
      
              }
          }
      }
      
      现在,我们需要确保从离开null检查到进入synchronized块期间,没有其他线程初始化了singleton。如果单例是在那个时候创建的,我们不想创建一个新的单例。这就是我们执行第二次空检查的原因:

      public Singleton getSingleton() {
          if(singleton == null) {
              synchronized(lock) {
                  if(singleton == null) {
                      //create
                  }
              }
          }
      }
      
      避免这种情况的更简单方法是使用按需初始化习惯用法:

      class Singleton {
          private static final Singleton SINGLETON = new Singleton();
      
          public static Singleton getSingleton() {
              return SINGLETON;
          }
      }
      
      其想法是让处理静态初始化(已经同步)的机制为您处理创建

      更简单的替代方法是
      枚举

      public enum Singleton {
          INSTANCE;
      }
      

      为了减少冗长,我通常使用
      GET
      而不是
      INSTANCE
      。这是假设您没有使用静态导入,如果是这样的话,您应该使用更合适的名称。

      您没有提到您的java版本,但这是我过去使用的。我有一些代码应该是类似于使用单次检查锁定的单例代码,当报表线程相互冲突时,在负载下会混淆报表。我使用了这个解决方案,名为:按需初始化持有者类习惯用法:

      public class Singleton {
              // Private constructor. Prevents instantiation from other classes.
              private Singleton() { }
      
              /**
               * Initializes singleton.
               *
               * {@link SingletonHolder} is loaded on the first execution of {@link Singleton#getInstance()} or the first access to
               * {@link SingletonHolder#INSTANCE}, not before.
               */
              private static class SingletonHolder {
                      private static final Singleton INSTANCE = new Singleton();
              }
      
              public static Singleton getInstance() {
                      return SingletonHolder.INSTANCE;
              }
      }
      

      它有效地创建了一个线程安全的单例。

      同步之前,需要执行空检查。这就是“双重检查”部分的来源。首先检查,然后同步,然后再次检查以确保它仍然为空。现在,每次访问singleton时都需要同步,这会影响性能。我强烈建议使用Josh Bloch的习惯用法:按需初始化,或者首先使用
      enum
      :难道
      getInstance():Object
      不是标准吗?第二:通常
      getInstance()
      调用私有构造函数,而不是相反的方法?另外,StackOverflow不用于对代码进行反馈。它是针对特定编程问题的。为了让您的代码得到审查,请在@VinceEmigh上发布他这样做了,但是在构造函数中。这和你说的是一样的,但我想他忘了写
      ,否则就回来了\u mySingleton可能重复的