单例模式一般分为:饿汉模式、懒汉模式、DCL模式、holder模式和枚举模式
一、饿汉模式
public class HungerySingleton {
private static HungerySingleton instance
= new HungerySingleton();
private HungerySingleton() {}
public static HungerySingleton
getInstance() {
return instance
;
}
}
优缺点:线程安全、没有延迟加载,长时间不使用,浪费内存
二、懒汉模式
public class HoonSingleton {
private static HoonSingleton singleton
= null
;
private HoonSingleton() {}
public static HoonSingleton
getInstance() {
if (null
== singleton
) {
singleton
= new HoonSingleton();
}
return singleton
;
}
}
优缺点:线程不安全,懒加载
三、DCL (Double Check Locking)模式
public class DCL {
private volatile static DCL instance
= null
;
private DCL() {}
public static DCL
getInstance() {
if (null
== instance
) {
synchronized (DCL
.class) {
if (null
== instance
) {
instance
= new DCL();
}
}
}
return instance
;
}
}
优缺点:线程安全,懒加载,性能好
Instance 前面为啥要加volataile?
因为:instance = new DCL();这句,不是原子操作,在jvm中可以分为3步:
给instance分配内存调用DCL的构造函数将instance对象指向分配的内存空间
上面第二步和第三步的顺序不能保证,如果指令重排之后,3先执行,2后执行,那么有线程来的时候,会判断instance是否为null,这时不为null,然后使用,但第一个线程还没将DCL初始化完成,那么就会报错。加了volataile之后,就会禁止指令重排。
五、holder模式
public class Holder {
private Holder() {}
private static class SingletonHolder {
private static final Holder INSTANCE = new Holder();
}
public static Holder getInstance() {
return SingletonHolder.INSTANCE;
}
}
优缺点:线程安全,懒加载
六、枚举模式
public class EnumSingleton {
private EnumSingleton() {}
private enum SinglletonEnum
{
INSTANCE
;
private EnumSingleton instance
= new EnumSingleton();
}
public static EnumSingleton
getInstance() {
return SinglletonEnum
.INSTANCE
.instance
;
}
}
优缺点:线程安全、懒加载、effective java作者推荐的模式
七、总结:
前5种好像用反射的方法,还是可以实例化多次,没有试过,枚举模式,用反射方法实例化会报错,所以是最安全的,也是effective Java作者极力推荐的