Java 关于辛格尔顿的事

Java 关于辛格尔顿的事,java,singleton,instance,Java,Singleton,Instance,最近我们介绍了单例模式,从那以后,我发现它有很多很好的用途,但是有一件很小的事情让我很烦。我注意到,在我所看到的每个singleton模式示例中,标准getInstance()方法如下所示: private static Singleton instance = null; public static Singleton getInstance() { if ( instance == null ) instance = new Singleton()

最近我们介绍了单例模式,从那以后,我发现它有很多很好的用途,但是有一件很小的事情让我很烦。我注意到,在我所看到的每个singleton模式示例中,标准getInstance()方法如下所示:

    private static Singleton instance = null;

    public static Singleton getInstance() {
    if ( instance == null ) 
        instance = new Singleton();
    return instance;
}
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
    return instance;
}
我想知道的是,检查实例变量是否为null有意义吗

如果您直接将实例变量分配给一个新的Singleton实例,并按如下方式返回它,它会起作用吗

    private static Singleton instance = null;

    public static Singleton getInstance() {
    if ( instance == null ) 
        instance = new Singleton();
    return instance;
}
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
    return instance;
}
很抱歉,如果这看起来像是浪费时间的问题,但我只是想知道是否有任何理由可以解释为什么第一个示例在任何地方都使用

谢谢你抽出时间


编辑:忘记将方法设置为静态。

这两种方法都是创建单例实例的有效方法。前者称为惰性初始化,后者称为急切初始化

如果创建单例实例的成本很高,那么延迟初始化将有所帮助。在这种情况下,仅在需要时创建singleton实例


另一方面,默认情况下,即时初始化是线程安全的。第一个示例是实例创建的延迟加载,其中对
getInstance
方法的第一个请求创建实例

为了避免在第一次方法调用时使用延迟加载(同时从多个线程)创建多个对象,必须同步对象创建

if (null == instance ) {
    synchronized (Singleton.class){
        if (null == instance ) {
            instance = new Singleton();
        }
    }
}

在第一个示例中,您仅在第一次真正需要时创建类的实例(惰性初始化)。因此,在需要该类之前,您将使用更少的内存

如果你有很多单例,如果你最终不需要它们,你就节省了内存和时间。

第一个例子(延迟加载)是非线程安全的;要使其线程安全,您可以将其

    private static volatile Singleton instance = null;
    private static final Object syncObj = new syncObj();

    public static Singleton getInstance() { // <- do not forget "static"
      // Double checked locking pattern
      if (instance != null) 
        return instance;

      synchronize(syncObj)  {
        if (instance != null) 
          return instance;

        instance = new Singleton();
      }

      return instance;
   }
private静态易失性单例实例=null;
私有静态最终对象syncObj=新syncObj();

publicstaticsingletongetinstance(){//请注意,如果您真的发现“它有很多很好的用途”您可能过度使用了它。使用单例的需求应该相对较少,尤其是如果您发现自己在每个应用程序中都使用了多个单例,那么您很可能没有正确设计应用程序。而且很可能存在“懒惰”模式的过度使用(因为人们不会问自己您正在问的问题)。在大多数使用单例的情况下,它将不可避免地被创建,延迟创建没有任何好处(在性能和线程相关的错误风险方面也有一些缺点)。这是一个比我预期的答案,但谢谢。另外,“它有很多很好的用途”这可能有点牵强,但我明白你的意思。当类最初加载时,由于应用程序中其他活动的顺序,无法创建单例时,也可以使用“懒惰”模式。