基于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(); //执行单例方法
}
}