单例模式最佳实践_The solution of Bill Pugh
基于Steve Quirk早先的工作,Bill Pugh实现了了一个适合所有版本的JVM、性能良好且线程安全的单例。此实现是依靠JVM对内部静态类&静态成员初始化的顺序(非并行)机制来实现的。
class Singleton { private Singleton() { } private static class LazySingleton { public static Singleton singleton = new Singleton(); } public static Singleton getInstance() { return LazySingleton.singleton; } }
该设计的执行流程是:
(1) 当JVM加载Singleton时,类Singleton首先进行初始化,由于该类并没有任何静态
变量需初始化,所以初始化过程很快完成。
(2) 直到JVM决定LazySingleton必须执行时,定义在Singleton中的静态内部类
LazySingleton才会初始化,也就是Singleton中的静态方法getInstance()被调用时,LazySingleton才会初始化。
(3) JVM第一次加载并初始化LazySingleton时,静态变量instance通过执行外部类
Singleton的私有构造函数而初始化。由于在JLS(Java Language Specification)中定义内部类初始化阶段是线性的、非并发的(serial, non-concurrent),所以无需再在静态的getInstance()方法中指定任何synchronized锁。
(4) 由于在类的初始化阶段,是以一种线性操作方式来写(而非无序访问)静态变量
singleton,(原文是writes the static variable singleton in a serial operation),所有对getInstance()后续的并发调用,将返回同样正确初始化的instance,而不会导致任何额外的同步负载。
一个测试例子:
步骤:
1 构造函数设置为private的
2 设置一个static类型的private的内部类,只有一个private的 static的 字段instance--单列的唯一实例
3 在static的getInstance方法中,返回2中的内部类的static字段instance--单列的唯一实例
public class TestSingleton { //构造函数 private private TestSingleton() { } //private 的静态内部类(static内部类) private static class LazySingleTon { //静态字段,类TestSingleton的唯一实例 private static TestSingleton singletonIntance = new TestSingleton(); } //获取单例的方法 public static TestSingleton getInstance() { return LazySingleTon.singletonIntance; } //单例的一个测试方法 public void testSingletonMethod() { System.out.println("testSingletonMethod() "); } public static void main(String[] args) { TestSingleton onlyOne = getInstance(); //获取单例 onlyOne.testSingletonMethod(); //执行单例方法 } }