单例模式一般分为:饿汉模式、懒汉模式、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作者极力推荐的