我什么时候应该使用惰性单例而不是普通单例?

Vee*_*nIn 6 java single-instance

到目前为止,我已经看到了两个单身人士的例子。

普通单身人士,

public class Singleton {
  private static Singleton instance;

  static {
    instance = new Singleton();
  }

  private Singleton() { 
    // hidden constructor
  }    

  public static Singleton getInstance() {
    return instance;
  }
}
Run Code Online (Sandbox Code Playgroud)

和懒惰的单身人士,

public class Singleton {

  private Singleton() { 
    // hidden constructor
  }

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

  public static Singleton getInstance() {
    return Holder.INSTANCE;
  }
}
Run Code Online (Sandbox Code Playgroud)

编码来自这个线程和这个用户。我最近才开始尝试学习单身人士,因为我以前的方法是

1.) 使用静态来创建类似......

static MyClass instance;
Run Code Online (Sandbox Code Playgroud)

2.) 我会尝试以一种看似奇怪的方式传递一个实例,

MyClass instance;

@Override
public void onEnable() { instance = this; }

// Transition to different class - - -

public OtherClass(MyClass myClass) {
    this.instance = myClass;
}
Run Code Online (Sandbox Code Playgroud)

最后,我的最终目标是什么?我主要使用它来将变量从我的主类传递到其他类。我目前正在尝试学习如何正确使用Files 和FileConfiguration,因此我想在整个课程中轻松分享它们。

如果我看起来像个初学者,与其特意告诉我学习 Java,不如先提供一个资源来帮助我解决我的问题。

Jon*_*nne 7

至于何时,而不是如何:当很有可能不需要对象时,我会使用单例或任何其他对象的延迟实例化,而当需要它的可能性很高时,我会使用立即实例化。一般来说,如果实例化失败,并且需要该对象,那么最好尽早失败。


Jac*_* G. 3

这个链接解释得相当好,甚至使用了一个类似的例子。

在软件工程中,按需初始化持有者(设计模式)惯用法是延迟加载的单例。在 Java 的所有版本中,该习惯用法都可以实现安全、高度并发的延迟初始化,并具有良好的性能。

关于为什么应该使用它:如果创建此实例的成本很高,那么此设计模式本质上是在需要时委托昂贵的计算,而不是在Singleton您的情况下首次访问外部类时。

另一个原因由另一个链接给出。它指出:

单例实现可以使用延迟初始化,其中实例是在第一次调用静态方法时创建的。如果可能同时从多个线程调用静态方法,则可能需要采取措施来防止可能导致创建该类的多个实例的竞争条件。