单例模式(Bill Pugh 的解决方案)
我正在阅读关于单例模式的维基,我不确定我是否理解这一点: https ://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom 部分内容正确。
所以简单来说:为什么 Bill Pugh 的解决方案比上面的例子更好?
是因为静态类在实际使用之前没有被 VM 加载还是类似的原因,所以我们不这样做在我们转向 getInstance() 方法之前创建对象? 另外,该方法仅在初始化对象的范围内是线程安全的吗?
I'm reading wiki about the singleton pattern and I'm not sure if I understand this: https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom part of it correctly.
So to make it simple: Why is Bill Pugh's solution better than the example above?
Is it because a static class is not load by the VM before it's actually used or something like this, so we don't create the object before we turn to the getInstance() method?
Also is that method thread safe only to the extent of initializing the object?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我认为 Pugh 先生的版本受到高度重视,因为它仅在调用 getInstance() 时执行单例实例化,即在加载类(持有 getInstance 方法的类)时不执行单例实例化。如果您的单例构造做了一些成本高昂的事情,那么这对您来说可能是一个优势。如果您像世界上大多数人一样,其单例只是为了避免静态方法(并且您还没有转向依赖注入框架),那么我不会为此失眠。
正如文章所述,Pugh 先生的方法比静态实例变量更惰性 - 但实际上,如果加载 Singleton 类,无论如何您都会调用 getInstance 方法。因此,作为一项计算机科学练习,它是有用的,但在现实世界中,它的好处是有争议的。
ps 我不太关心 Bloch 先生在这里的例子,因为使用枚举就是说 My Singleton IS-A 枚举,这对我来说听起来不太正确(特别是来自那些正确地说永远不要实现接口的人)获取常数)
I think Mr Pugh's version is held in high regard because it only performs the instantiation of the singleton when
getInstance()
is called i.e. not when the class (the class holding the getInstance method) is loaded. If your singleton construction does something costly then this may be an advantage for you. If you're like the majority of the world whose singletons are just to avoid static methods (and you haven't moved onto dependency injection frameworks), then I would not lose any sleep over it.As the article states, Mr Pugh's method is lazier than the static instance variable - but in reality if the Singleton class gets loaded you're going to be calling the getInstance method anyhow. So as a computer science exercise it's useful, but in the real world its benefits are debatable.
p.s. I don't care much for Mr Bloch's example here as to use an enum would be to say My Singleton IS-A enum, which doesn't sound right to me (especially from someone who, rightly, says never implement an interface just to get the constants)
JLS 保证类仅在第一次使用时才加载(使得单例初始化变得懒惰),并且类加载是线程安全的(使得
getInstance()< /code> 方法也是线程安全的)
至于为什么线程安全
因为第一次调用 getInstance() 时,JVM 会加载holder类。如果另一个线程同时调用 getInstance(),JVM 不会第二次加载 Holder 类:它会等待第一个线程完成类加载,并在 Holder 类加载和初始化结束时,两个线程都会看到持有者类已正确初始化,因此包含唯一的单例实例。
The JLS guarantees that a class is only loaded when it's used for the first time (making the singleton initialization lazy), and that the class loading is thread-safe (making the
getInstance()
method thread-safe as well)As for why thread-safe
Because the first time getInstance() is called, the JVM will load the holder class. If another thread calls getInstance() concurrently, the JVM won't load the holder class a second time: it will wait for the first thread to have completed the class loading, and at the end of the loading and initialization of the holder class, both thread will see the holder class properly initialized and thus containing the unique singleton instance.
不只是静态类,任何类。类在被引用之前不会被加载。请参阅 JLS - 12.4.1 何时发生初始化
确切地。
分发引用是线程安全的,因此该方法始终是线程安全的,而不仅仅是在创建时
Not just a static class, any class. Classes aren't loaded until they are referenced. See the JLS - 12.4.1 When Initialization Occurs
Exactly.
Handing out a reference is thread-safe, so this method is always thread-safe, not just at creation time
解释的关键部分如下:
Bill Pogh 的解决方案提供了惰性。
The key part of the explanation is the following:
Bill Pogh's solution provides laziness.
正确的。
它确保只创建一个实例,并且除了对该完全初始化的实例的引用之外,任何客户端都不会收到任何内容。
Correct.
It ensures that only one instance is created and no client receives anything but a reference to that fully initialized instances.
静态内部类将包含 Singleton 实例。当静态内部类加载到内存中时,它将创建 Singleton 实例。它不需要同步。
公共类单例{
}
Static inner class will contain the Singleton instance. It will create the Singleton instance when the static inner class is loaded into the memory. It doesn't require synchronization.
public class Singleton {
}