单例模式之饿汉式、懒汉式、dcl双重检查锁、静态内部类、枚举类

单例模式有很多实现方法,饿汉、懒汉、静态内部类、枚举类,试分析每种实现下获取单例对象(即调用
getInstance)时的线程安全,并思考注释中的问题
饿汉式:类加载就会导致该单实例对象被创建
懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建
实现1:饿汉式
// 问题1:为什么加 final
// 问题2:如果实现了序列化接口, 还要做什么来防止反序列化破坏单例
public final class Singleton implements Serializable {
	// 问题3:为什么设置为私有? 是否能防止反射创建新的实例?
	private Singleton() {}
	// 问题4:这样初始化是否能保证单例对象创建时的线程安全?
	private static final Singleton INSTANCE = new Singleton();
	// 问题5:为什么提供静态方法而不是直接将 INSTANCE 设置为 public, 说出你知道的理由
	public static Singleton getInstance() {
		return INSTANCE;
	}
	public Object readResolve() {
		return INSTANCE;
	}
}
实现2:枚举类
// 问题1:枚举单例是如何限制实例个数的
// 问题2:枚举单例在创建时是否有并发问题
// 问题3:枚举单例能否被反射破坏单例
// 问题4:枚举单例能否被反序列化破坏单例
// 问题5:枚举单例属于懒汉式还是饿汉式
// 问题6:枚举单例如果希望加入一些单例创建时的初始化逻辑该如何做
public class SingletonObject7 {


    private SingletonObject7(){

    }

    /**
     * 枚举类型是线程安全的,并且只会装载一次
     */
    private enum Singleton{
        INSTANCE;

        private final SingletonObject7 instance;

        Singleton(){
            instance = new SingletonObject7();
        }

        private SingletonObject7 getInstance(){
            return instance;
        }
    }

    public static SingletonObject7 getInstance(){

        return Singleton.INSTANCE.getInstance();
    }
}

作者:平头哥的技术博文
链接:https://juejin.cn/post/6844903925783461896
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
实现3:懒汉式之synchronized同步,但是锁的粒度太大
public final class Singleton {
	private Singleton() { }
	private static Singleton INSTANCE = null;
	// 分析这里的线程安全, 并说明有什么缺点
	public static synchronized Singleton getInstance() {
	if( INSTANCE != null ){
		return INSTANCE;
	}
	INSTANCE = new Singleton();
		return INSTANCE;
	}
}
实现4:DCL双重检查锁
public final class Singleton {
	private Singleton() { }
	// 问题1:解释为什么要加 volatile ?
	private static volatile Singleton INSTANCE = null;
	// 问题2:对比实现3, 说出这样做的意义
	public static Singleton getInstance() {
		if (INSTANCE != null) {
			return INSTANCE;
		}
		synchronized (Singleton.class) {
			// 问题3:为什么还要在这里加为空判断, 之前不是判断过了吗
			if (INSTANCE != null) { // t2
				return INSTANCE;
			}
			INSTANCE = new Singleton();
			return INSTANCE;
		}
	}
}
实现5:静态内部类
public final class Singleton {
	private Singleton() { }
	// 问题1:属于懒汉式还是饿汉式
	private static class LazyHolder {
		static final Singleton INSTANCE = new Singleton();
	}
	// 问题2:在创建时是否有并发问题
	public static Singleton getInstance() {
		return LazyHolder.INSTANCE;
	}
}
上一篇:单例模式总结


下一篇:java设计模式:单例模式 (学习笔记3):