美文网首页
单例模式

单例模式

作者: 谢凯 | 来源:发表于2016-06-24 11:14 被阅读0次

    单例模式(Singleton Pattern):确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全局访问的方法。单例模式是一种对象创建型模式。

    单例模式结构图.jpg
    • Singleton(单例)

    在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。

    但是这样写,并不能满足只生成一个实例的要求。如果 Singleton的构造方法中需要执行耗时操作,那么当第二次调用getInstance时,为null的条件依然成立,所以会产生多个实例。

    以下是两个优化过后的单例模式

    • 饿汉式单例模式
    class EagerSingleton {   
        private static final EagerSingleton instance = new EagerSingleton();   
        private EagerSingleton() { }   
      
        public static EagerSingleton getInstance() {  
            return instance;   
        }     
    } 
    

    当类被加载时,静态的私有成员变量 instance 就被初始化,并且只会创建一次,不会产生多个实例。

    • 懒汉式单例模式
    class LazySingleton {   
        private volatile static LazySingleton instance = null;   
      
        private LazySingleton() { }   
      
        public static LazySingleton getInstance() {   
            //第一重判断  
            if (instance == null) {  
                //锁定代码块  
                synchronized (LazySingleton.class) {  
                    //第二重判断  
                    if (instance == null) {  
                        instance = new LazySingleton(); //创建单例实例  
                    }  
                }  
            }  
            return instance;   
        }  
    }  
    

    依靠synchronized关键字锁定代码块,来确保多线程调用情况下的安全性,也不会产生多个实例。

    • 饿汉式单例在类被加载的时候就实例化了自己,确保了唯一性,也不用考虑多线程访问的问题。但是不管系统是否需要该实例对象,都会创建。且在系统刚加载的时候,时间会增加。

    • 懒汉式单例在第一次需要使用的时候才会创建实例,因此不会浪费系统资源,并且通过双重检查锁,volatile 等关键字来控制,会影响系统性能。

    • java语言最好的单例模式写法 Initialization Demand Holder (IoDH)
    //Initialization on Demand Holder  
    class Singleton {  
        private Singleton() {  
        }  
          
        private static class HolderClass {  
                private final static Singleton instance = new Singleton();  
        }  
          
        public static Singleton getInstance() {  
            return HolderClass.instance;  
        }  
    }  
    

    由于静态单例对象没有作为Singleton的成员变量直接实例化,因此类加载时不会实例化Singleton,第一次调用getInstance()时将加载内部类HolderClass,在该内部类中定义了一个static类型的变量instance,此时会首先初始化这个成员变量,由Java虚拟机来保证其线程安全性,确保该成员变量只能初始化一次。由于getInstance()方法没有任何线程锁定,因此其性能不会造成任何影响。

    相关文章

      网友评论

          本文标题:单例模式

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