美文网首页
单例模式

单例模式

作者: wangdy12 | 来源:发表于2017-07-15 20:40 被阅读0次

    Singleton pattern

    限定类对象只有一个实例
    核心原理是将构造函数私有化,并且通过静态方法获取一个唯一的实例,在这个过程中保证线程安全。

    饿汉模式

    实例在类加载初始化的时候就由<clinit>函数创建

    public final class Singleton {
        private static final Singleton INSTANCE = new Singleton();
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            return INSTANCE;
        }
    }
    

    缺点:饿汉模式初始化的过早,如果仅仅调用了单例类的静态函数,也会进行初始化


    懒汉模式

    延迟加载:在使用时才初始化,效率高,第一次加载反应稍慢
    通过 double-checked locking 双重检查锁定,实现线程安全

    public final class Singleton {
        private static volatile Singleton instance = null;
    
        private Singleton() {}
    
        public static Singleton getInstance() {
            if (instance == null) {
                synchronized(Singleton.class) {
                    if (instance == null) {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
    

    volatile的作用:保证变量可见性和禁止指令重新排序
    在这里主要是避免指令重排,否则Singleton实例分配对象后,可能直接将instance指向对应的内存空间,而构造函数还在初始化成员字段,此时另一个线程就会直接使用尚未初始化完成的单例对象instance,可能产生错误


    静态内部类

    线程安全,延迟了实例化,只有在调用getInstance时才会实例化

    public final class Singleton{
        private Singleton(){}
        public static Singleton getInstance(){
            return SingletonHolder.INSTANCE;
        }
    
        private static class SingletonHolder{
            private static final Singleton INSTANCE = new Singleton();
        }
    }
    

    静态内部类的加载不需要依附外部类,在使用时才加载。不过在加载静态内部类的过程中也会加载外部类


    枚举单例

    写法简单,通过Singleton.INSTANCE.getInstance()获取单例

    class Resource{
    }
    
    public enum Singleton{
        INSTANCE;
        private Resource instance;
        Singleton() {
            instance = new Resource();
        }
        public Resource getInstance() {
            return instance;
        }
    }
    
    • enum没有public的构造器,防止外部的额外构造,恰好和单例模式吻合
    • 用枚举实现单例,类似于饿汉模式,没有实现延迟实例化
    • 枚举的反序列化不会生产新的实例

    容器类

    将多种单例类型注入到一个统一管理的容器中,在使用时根据key获取对应类型的对象。这种方式可以管理多种类型的单例,使用统一的接口进行获取操作

    public class SingletonManager { 
      private static Map<String, Object> objMap = new HashMap<String,Object>();
      private Singleton() { 
      }
      public static void registerService(String key, Objectinstance) {
        if (!objMap.containsKey(key) ) {
          objMap.put(key, instance) ;
        }
      }
      public static ObjectgetService(String key) {
        return objMap.get(key) ;
      }
    }
    

    相关文章

      网友评论

          本文标题:单例模式

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