设计模式 - 单例模式

105 阅读1分钟

1. 饿汉式 (在类装载的时候完成实例化)

public class Singleton01 {
    private  static final Singleton01 singleton ;

    static{
    	// 当类加载器加载的时候直接加载       
        singleton = new Singleton01();
    }

    private Singleton01(){}

    public  static Singleton01 getSingleton(){
        return singleton;
    }

    public static void main(String[] args) {
        Singleton01 singleton = Singleton01.getSingleton();
        Singleton01 singleton1 = Singleton01.getSingleton();
        System.out.println(singleton == singleton1);
    }
}

2. 懒汉式 (需要的时候才要加载)

  • 最简单的方式 就是 静态内部类
public class Singleton {
    //3.构造方法私有化
    private Singleton(){}

    // 1.写一个静态内部类
    private static class SingletonInstance{
        private static final Singleton singleton = new Singleton();
    }
    // 2.实现加载
    public static Singleton getInstance(){
        return SingletonInstance.singleton;
    }
}
  • 双重检查 ,进行同步
public class DoubleCheckSingleton {

    // 保证可见性
    private static volatile DoubleCheckSingleton instance;

    private DoubleCheckSingleton(){

    }

    public static DoubleCheckSingleton getInstance(){
		// 检测 1
        if (null == instance) {
            synchronized (DoubleCheckSingleton.class) {
                // 检测 2
                if (null == instance) {
                    instance = new DoubleCheckSingleton();
                }
            }
        }
        return instance;
    }
}

3. CAS 实现

public class Singleton {
    private static final AtomicReference<Singleton> INSTANCE = new AtomicReference<>();

    private Singleton() {}

    public static Singleton getInstance() {
        for (; ; ) {
            Singleton singleton = INSTANCE.get();
            if (null != singleton) {
                return singleton;
            }
            // 这里可以实例化很多对象
            singleton = new Singleton();

            // 但是只能设置成功一个对象
            if (INSTANCE.compareAndSet(null, singleton)) {
                return singleton;
            }
        }
    }
}

5. 对比使用单例模式 和 普通模式内存差异

很显然单例模式 占用内存小

普通的创建对象 ,JVM会自动回收 ,这种方式也很好 , 但是我们知道GC回收, 会全局进行锁操作 ,所以回收很耗时