【翻译自维基百科 http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom,并进行适当增删】
可能你听过,使用单例模式(singleton)会有线程安全问题,当然可以通过同步加锁等方法解决。但,更简单的方法请看本文。
在软件工程中,Initialization-on-demand holder 这个习语指的就是延迟加载的单例模式。在所有Java的版本里,这个方法都能达到安全、高效的实现高并发的延迟初始化。
代码结构如下:
public class Something {
private Something() {}
private static class LazyHolder {
private static final Something INSTANCE = new Something();
}
public static Something getInstance() {
return LazyHolder.INSTANCE;
}
}
这种实现依赖于在JVM中初始化阶段的特性,这在java 语言说明里有交代。当一个类被JVM加载,这个类就会历经初始化的过程。既然这个类没有其他静态的变量需要初始化,那么初始化过程就会顺利完成。而定义在类里面的静态类LazyHolder直到JVM确定LazyHolder一定会被执行时才会去初始化。当静态方法getInstance调用时,静态类LazyHolder才会被执行,当这件事第一次发生时,JVM就会去加载并初始化LazyHolder。
LazyHolder 的初始化导致了静态变量INSTANCE因为外部类(就是指LazyHolder)执行私有的构造器而被初始化。由于类的初始化过程是串行的(由java语言说明保障),就无需并行同步操作了。
并且,因为初始化阶段在串行操作里写入静态变量INSTANCE,所有接下来的并行调用getInstance方法会正确返回相同的INSTANCE,而不需要额外的同步开销。