单例模式Bill Pugh解

问题描述

| 我正在阅读有关单例模式的Wiki,但不确定我是否理解这一点:https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom部分正确。 如此简单:为什么Bill Pugh的解决方案比上面的示例更好? 是因为VM在实际使用静态类之前还是没有加载静态类,或者这样的事情,所以我们在转到getInstance()方法之前不创建对象吗? 同样,该方法线程仅在初始化对象的程度上安全吗?     

解决方法

我认为Pugh先生的版本受到高度重视,因为它仅在调用
getInstance()
时执行单例的实例化,即在加载类(包含getInstance方法的类)时不执行。如果您的单例构造成本高昂,那么这可能对您有利。如果您像世界上大多数人那样,单身只是为了避免使用静态方法(并且您还没有迁移到依赖项注入框架),那么我不会为之沉迷。 如文章所述,Pugh先生的方法比静态实例变量懒惰-但实际上,如果加载了Singleton类,您将无论如何都将调用getInstance方法。因此,作为计算机科学练习,它很有用,但在现实世界中,其好处值得商are。 ps。我不太在意Bloch先生在此处的示例,因为使用枚举将是说My Singleton IS-A枚举,这对我来说听起来不正确(尤其是从某个人那里,他说对了,实现一个接口只是为了获取常量)     ,JLS保证仅在第一次使用某个类时才加载该类(使单例初始化延迟),并且该类加载是线程安全的(也使
getInstance()
方法也成为线程安全的) 至于为什么线程安全 因为是第一次调用getInstance(),所以JVM将保存Holder类。如果另一个线程同时调用getInstance(),则JVM将不会再次加载Holder类:它将等待第一个线程完成类加载,并在Holder类的加载和初始化结束时等待,两个线程都会看到正确初始化了holder类,因此包含了唯一的单例实例。     ,  是因为静态类不是   由VM实际加载之前   用过的 不只是静态类,任何类。在引用它们之前,不会加载类。请参阅JLS-发生初始化时的12.4.1   或类似的东西,所以我们不   在转向之前创建对象   getInstance()方法? 究竟。   也是该方法线程仅安全   达到初始化的程度   宾语? 发出引用是线程安全的,因此此方法始终是线程安全的,而不仅仅是在创建时     ,  是因为静态类不是   由VM实际加载之前   用过的或类似的东西,所以我们   在转身之前不要创建对象   到getInstance()方法? 正确。   同样,该方法线程仅在初始化对象的程度上安全吗? 它确保仅创建一个实例,并且除了对完全初始化实例的引用之外,没有客户端会收到任何东西。     ,解释的关键部分如下:   嵌套类被引用为否   较早(因此没有加载   比类加载器更早)   getInstance()被调用的那一刻。   因此,此解决方案是线程安全的   无需特殊语言   构造(即volatile或   同步)。 Bill Pogh的解决方案提供了惰性。