美文网首页
设计模式-单例(Singleton)模式

设计模式-单例(Singleton)模式

作者: qyfl | 来源:发表于2019-10-17 17:38 被阅读0次

主要角色

  • 单例模式本身

职责

在任何情况下,都绝对只有一个实例

代码

基础版

线程安全

public class Singleton{
    private static Singleton singleton;

    static{
        singleton = new Singleton();
    }
    
    private Singleton(){
        // do something
    }

    public static Singleton getInstance(){
        return singleton;
    }
}
问题
  1. 可以使用反射的方式创建不止一个单例。
  2. 单例如果不使用还是被创建出来了。

懒汉模式-用的时候在创建

不能使用反射创建。
线程安全

public class LazySingleton {
    private static LazySingleton lazySingleton = null;
    private LazySingleton(){
        if(lazySingleton != null){
            throw new RuntimeException("单例构造器禁止反射调用");
        }
    }
    public synchronized static LazySingleton getInstance(){
        if(lazySingleton == null){
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}
问题
  1. synchronized 加在 static 方法上,实际上就是加在类上。性能不高。

懒汉双重检查锁模式-兼顾线程安全和性能问题

使用 volatile 避免指令重排序

public class LazyDoubleCheckSingleton {
    private volatile static LazyDoubleCheckSingleton lazyDoubleCheckSingleton = null;
    private LazyDoubleCheckSingleton(){

    }

    public static LazyDoubleCheckSingleton getInstance(){
        if(lazyDoubleCheckSingleton == null){
            synchronized (LazyDoubleCheckSingleton.class){
                if(lazyDoubleCheckSingleton == null){
                    lazyDoubleCheckSingleton = new LazyDoubleCheckSingleton();
                    // 1.分配内存给这个对象
                    // 2.初始化对象
                    // 3.设置lazyDoubleCheckSingleton 指向刚分配的内存地址
                    // 可能会出现指令重排序,执行顺序变成 1->3->2,的时候,另一个线程判断 lazyDoubleCheckSingleton 不为,直接返回了。
                }
            }
        }
        return lazyDoubleCheckSingleton;
    }
}

静态内部类模式

懒汉双重检查锁模式作用相同,只是使用静态内部类来避免指令重排序。

public class StaticInnerClassSingleton {
    private static class InnerClass{
        private static StaticInnerClassSingleton staticInnerClassSingleton = new StaticInnerClassSingleton();
    }
    public static StaticInnerClassSingleton getInstance(){
        return InnerClass.staticInnerClassSingleton;
    }

    private StaticInnerClassSingleton(){
        if(InnerClass.staticInnerClassSingleton != null){
            throw new RuntimeException("单例构造器禁止反射调用");
        }
    }
}

枚举模式

public enum Singleton {
    INSTANCE;

    public void whatever() {
    }
}

技巧

  • 因为单例的特性,和并发的特性相似,所以特别要注意线程安全问题。
  • 因为单例模式经常被问到,所以单例模式的实现会多样。

相关文章

网友评论

      本文标题:设计模式-单例(Singleton)模式

      本文链接:https://www.haomeiwen.com/subject/oydvmctx.html