单例设计模式
1.饿汉式
代码实现:
public class Test { public static void main(String[] args) { Single single = Single.getSingle(); } } class Single{ private Single(){} private static Single s = new Single(); public static Single getSingle(){ return s; } }
2.懒汉式
延迟加载, 只有在真正使用的时候,才开始实例化。
double check 加锁优化
编译器(JIT),CPU 有可能对指令进行重排序,导致使用到尚未初始化 的实例,可以通过添加volatile 关键字进行修饰, 对于volatile 修饰的字段,可以防止指令重排。
代码实现:
class Single { // 禁止指令重排 private volatile static Single s; private Single() { } public static Single getSingle() { if (s == null) { synchronized (Single.class) { if (s == null) { s = new Single(); // 字节码层 // JIT , CPU 有可能对如下指令进行重排序 // 1 .分配空间 // 2 .初始化 // 3 .引用赋值 // 如重排序后的结果为如 // 1 .分配空间 // 3 .引用赋值 如果在当前指令执行完,有其他线程来获取实例,将拿到尚未初始化好的实例 // 2 .初始化 } } } return s; } }
2.静态内部类
本质上是利用类的加载机制来保证线程安全
只有在实际使用的时候,才会触发类的初始化,所以也是懒加载的一 种形式。
代码实现:
class Single { private static class InnerSingle { private static Single s = new Single(); } private Single() { // 防止利用反射攻击 if(InnerSingle.s == null){ throw new RuntimeException("单例不允许多个实例"); } } public static Single getSingle() { return InnerSingle.s; } }
4.枚举类
天然不支持反射创建对应的实例,且有自己的反序列化机制
利用类加载机制保证线程安全
代码实现:
public enum EnumSingleton { INSTANCE; }