Java单例模式以及线程安全性的保证



1.单例模式有什么用处?java

有一些对象只能使用一个,例如:数据库链接、线程池(threadpool)、缓存(cache)、对话框、处理偏好(preferences)设置和这侧表(registry)的对象、日志对象、充当打印机、显卡等设备的驱动程序的对象,即用于管理共享的资源。这种对象只能有一个实例,制造多个会致使问题。数据库


2.最经典的单例模式?缓存

        /**
     * 1.利用一个私有静态变量来记录Singleton类的惟一实例;
     * 2.构造器声明为私有,只有Singleton类自己内部才可调用;
     * 3.声明共有静态的方法getInstance()来实例化对象,并返回这个对象的实例;
     * 4.说明:若是咱们不须要这个实例,就不会调用getInstance()方法,那么这个实例就不会产生,
     *        称为“延迟实例化(lazy instantiaze)”。这种作法对资源敏感的对象特别重要。
     */
    public class Singleton {
    
        private static Singleton sInstance;
        
        private Singleton(){}
        
        public static Singleton getInstance(){
            if(sInstance == null){
                sInstance = new Singleton();
            }
            return sInstance;
        }
    }

3.单例模式定义--确保一个类只有一个实例,并提供一个全局访问点
安全

(1)全局访问点即向外提供的获取惟一实例的惟一入口,是共有静态的,访问它对比访问通常的全局变量的优势在于:单例中的全局访问点能够作到“延迟实例化”。多线程

(2)此时的单例可能遇到的麻烦--多线程ide

         正以下图中状况所示,当有多个线程同时访问该访问点时,以两个线程为例,就会出现可能实例化两个对象,这对于使用单例的地方可能引起灾难呀...
spa

wKioL1aXabSTXBuEAACodDIn338308.jpg


4.怎样改善多线程状况下的单例?线程

(1)不推荐的方法--synchronized日志

        同步getInstance()方法既简单又有效,可是可能形成程序执行效率降低100倍,若是getInstance()被调用的频繁,只能从新考虑其余方法了;对象

(2)什么都不作

        没错,什么都不作。若是应用程序能够接受getInstance()形成的额外负担,那就彻底能够忘记这件事;

(3)使用“急切实例化(eagerly)”而非“延迟实例化”的作法

        a.若是应用程序老是须要建立使用单例实例;

        b.若是应用程序在建立运行时方面的负担不过重;

        此时可选择“急切实例化”:

        public class EagerlySingleton {        
            /**在静态初始化器中建立单例实例,保证了线程安全**/
            private static EagerlySingleton eSingletonInstance = new EagerlySingleton();
            
            private EagerlySingleton(){};
            
            public static EagerlySingleton getInstance(){
                return eSingletonInstance;
            }
        }

        这个作法,依赖JVM在加载这个类时就建立这个惟一的单例实例,保证了任何线程在访问这个静态变量以前,该实例已经建立。

(4)用“双重检查加锁(double checked locking)”,在getInstance()中减小使用同步

    /**    
     * 1.volatile确保实例化时,多个线程能正确的处理sInstance;
     * 2.判断sInstance == null后在使用synchronized,且synchronized后在判断一次sInstance == null
     * 3.双重检查加锁不适用于1.4以及更早的版本的Java。
     */
    public class DoubleCheckSingleton {
    
        private volatile static DoubleCheckSingleton sInstance;
        
        private DoubleCheckSingleton(){}
        
        public static DoubleCheckSingleton getInstance(){
            if(sInstance == null){
                synchronized (DoubleCheckSingleton.class) {
                    if(sInstance == null){
                        sInstance = new DoubleCheckSingleton();
                    }
                }
            }
            return sInstance;
        }
    }
相关文章
相关标签/搜索