天天看点

几种单例模式

几种单例模式

枚举可以天然防止反射和反序列化漏洞 需要延时加载时:枚举好于饿汉式 ,不需要延时加载:静态内部类好于懒汉式 也就是说优先选用 枚举和静态内部类

饿汉

/**
 * 饿汉式单例设计模式
 * 特点:线程安全、调用效率高、资源利用率低(无懒加载)。
 *
 * @author tiger
 * @Date 2017年9月2日
 */
public class SingletonHungry {
    // 私有构造函数
    private SingletonHungry() {  }

    // 单例对象,static是天然的线程安全
    private static SingletonHungry instance = new SingletonHungry();

    // 静态的工厂方法(访问本类的唯一入口)
    public static SingletonHungry getInstance() {
        return instance;
    }
}      

懒汉1

对方法添加synchronized

/**
 * 懒汉式单例设计模式||特点:线程安全、调用效率低、资源利用率高(有懒加载)。
 * @author tiger
 * @Date 2017年9月2日
 */
public class SingletonLazy {
    // 私有化构造器
    private SingletonLazy() {}

    private static SingletonLazy instance = null;
    
    // 对方法进行同步(synchronized)并发效率低。
    public synchronized static SingletonLazy getInstance(){
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}      

懒汉2

静态内部类

/**
 * 静态内部类单例子模式
 * 特点:线程安全、兼备了高并发和延迟加载优势(有懒加载)。
 *
 * @author tiger
 * @Date 2017年9月2日
 */
public class SingletonLazyInnerClass {

    // 私有构造函数,杜绝反射机制破坏
    private SingletonLazyInnerClass() {
        if (LazyHolder.LAZY != null) {
            throw new RuntimeException("不允许创建多个实例");
        }
    }

    // 在静态内部类里创建类的实例
    private static class LazyHolder {
        private static final SingletonLazyInnerClass LAZY = new SingletonLazyInnerClass();
    }

    // 提供一个外界调用的公共方法,需要调用的时候才会初始化静态内部类,不需要线程同步,从而兼备了 
    // 高并发需求
    public static final SingletonLazyInnerClass getInstance() {
        // 在返回结果以前,一定会先加载内部类
        return LazyHolder.LAZY;
    }
}      

懒汉3

/**
 * 懒汉模式 -》 双重同步锁单例模式
 * 单例实例在第一次使用时进行创建
 */
public class SingletonDoubleCheck {

    // 私有构造函数
    private SingletonDoubleCheck() { }

    // 1、memory = allocate() 分配对象的内存空间
    // 2、ctorInstance() 初始化对象
    // 3、instance = memory 设置instance指向刚分配的内存

    // 单例对象 volatile + 双重检测机制 -> 禁止指令重排
    private volatile static SingletonDoubleCheck instance = null;

    // 静态的工厂方法
    public static SingletonDoubleCheck getInstance() {
        if (instance == null) { // 双重检测机制        // B
            synchronized (SingletonDoubleCheck.class) { // 同步锁
                if (instance == null) {
                    instance = new SingletonDoubleCheck(); // A - 3
                }
            }
        }
        return instance;
    }
}      

懒汉4-推荐

/**
 * 枚举模式:最安全
 */
public class SingletonEnum {

    // 私有构造函数
    private SingletonEnum() { }

    public static SingletonEnum getInstance() {
        return LazyHolder.INSTANCE.getInstance();
    }

    // 枚举内部类
    private enum LazyHolder {
        INSTANCE;

        private SingletonEnum singleton;

        // JVM保证这个方法绝对只调用一次
        LazyHolder() {
            singleton = new SingletonEnum();
        }

        public SingletonEnum getInstance() {
            return singleton;
        }
    }
}