Java 关于静态holder单态模式

Java 关于静态holder单态模式,java,Java,我已经在很多方面开发了单例,这取决于条件,比如volatile/lazy单例、eager单例、normal单例和through-Enum,但我特别想了解下面所示的静态holder模式单例 public static class Singleton { private static class InstanceHolder { public static Singleton instance = new Singleton(); } private Sin

我已经在很多方面开发了单例,这取决于条件,比如volatile/lazy单例、eager单例、normal单例和through-Enum,但我特别想了解下面所示的静态holder模式单例

public static class Singleton {
    private static class InstanceHolder {
        public static Singleton instance = new Singleton();
    }

    private Singleton(){}

    public static Singleton getInstance() { 
        return InstanceHolder.instance;
    }
}

请告知在哪些条件下它是有益的,以及它的好处是什么。

这是一种利用JVM加载类的方式来创建线程安全的惰性单例的方法。您可以在Bloch的高效Java书籍中阅读更多关于为什么以及如何正确实现它的内容


请记住,从可测试代码的角度来看,单例(以及一般的全局状态)是没有好处的,应该避免使用。

这种模式的好处至少有三个原因:

  • 静态工厂
  • 延迟初始化
  • 线程安全

  • JVM会推迟初始化InstanceHolder类,直到它被实际使用为止,而且由于Singleton是使用静态初始值设定项初始化的,因此不需要额外的同步。任何线程对getInstance的第一次调用都会导致InstanceHolder被加载和初始化,此时单例的初始化通过静态初始值设定项进行


    静态保持器模式也被认为是双重检查锁定反模式的最聪明的替代品。

    关于这一点已经有很多问题,但不使用单例的一个很好的理由是很难测试。您的实现不正确。实例应该是final。是的,事实上,
    Instance
    实际上可以是
    private static final
    。Java中不能有顶级的
    static
    类!您需要将第一行更改为:
    public class Singleton
    。请看:@jdb为什么?它是强制性的吗?+1用于实际回答OPs的“好处是什么”问题。“由于单例是用静态初始值设定项初始化的,所以不需要额外的同步”-我对这句话很好奇。在引擎盖下,JVM必须进行同步,以确保没有竞争,对吗?@bh1988-否。初始化步骤是按顺序进行的,因此不需要同步。@bhh1988我认为“不需要额外的同步”是指作为程序员显式进行同步。JVM(类加载器)在内部处理这个问题。