饿汉式
public class SingletonObject1 {
private SingletonObject1() {
}
private static final SingletonObject1 INSTANCE = new SingletonObject1();
public static SingletonObject1 getInstance() {
return INSTANCE;
}
}
线程安全,类加载时就创建实例,java内部就使用到了这种方式。
双重锁判断
public class SingletonObject2 {
private SingletonObject2() {
}
private static volatile SingletonObject2 INSTANCE;
public static SingletonObject2 getInstance() {
if (INSTANCE == null) {
synchronized (SingletonObject2.class) {
if (INSTANCE == null) {
INSTANCE = new SingletonObject2();
}
}
}
return INSTANCE;
}
}
new一个对象之后,这个对象可能还没有完全构造成功,另外的线程使用就可能出问题,volatile关键字可以禁止指令重排序,避免此问题。
Spring中的ReactiveAdapterRegistry和DefaultConversionService都使用到了这种方式。
静态内部类
public class SingletonObject3 {
private SingletonObject3() {
}
private static class SingletonObject3Holder {
private static final SingletonObject3 INSTANCE = new SingletonObject3();
}
public static SingletonObject3 getInstance() {
return SingletonObject3Holder.INSTANCE;
}
}
jvm保证线程安全性,延迟加载,推荐使用。
枚举
public enum SingletonObject4 {
INSTANCE;
public static SingletonObject4 getInstance() {
return INSTANCE;
}
}
jvm保证线程安全,并且可以防止反射攻击,克隆攻击和反序列化攻击。
总结
单例模式的本质就是控制实例数量,可以扩展到多例。