单例模式分为饿汉式和懒汉式两种,饿汉式单例模式在类加载时就实例化了,从资源利用角度来看,它就不及懒汉式好。而懒汉时由于有同步块的影响,在性能上比较差。于是,就有人设计出了下面的双重检测成例单利模式。似乎找到了他们之间的平衡点。
public class DoubleCheck {
private static DoubleCheck instance = null;
private DoubleCheck() { }
public static DoubleCheck getInstance() {
if (instance == null) {
synchronized (DoubleCheck.class) {
if (instance == null) {
instance = new DoubleCheck();
}
}
}
return instance;
}
}
这种设计在C中的确用得很多。但是很可惜,在Java中,上述的类并不能很好的工作,它很可能导致系统崩溃。在java中,引用(注意:不是引用的实例)是放在栈中的,而它指向的实例是在堆中。并且实例实例化(new)的时间是很长的。当线程1进入到第二个if块里时,在引用被创建而实例还没有初始化完时,线程2判断第一个if,此时引用不为空,方法直接返回instance。这时系统将崩溃,是因为JDK不允许返回一个没有实例化完的对象。所以在Java中不要用双重检测成例。