美文网首页
单例模式

单例模式

作者: gaaaaaaaaaao | 来源:发表于2016-10-19 20:27 被阅读0次

    单例模式简单的讲就是保证一个类最多只有一个实例。

    • 懒汉单例:即用到的时候再进行实例化。

        public class SingleTon {
        
            private static SingleTon singleTon;
        
            private SingleTon() {
        
            }
        
            public static SingleTon getInstance() {
                if (singleTon == null) {
                    singleTon = new SingleTon();
                }
                return singleTon;
            }
        }
      

    上述实现方式的缺陷是很明显的,即不是线程安全的。设想如下情况:线程1在运行到判断singleTon == null之后被切换到线程2,则线程2页会进行singleTon == null的判断,然后线程2创建了一个实例,然后切换回线程1,继续执行,还会创建一个实例。

    • 懒汉修改1

        public class SingleTon {
        
            private static SingleTon singleTon;
        
            private SingleTon() {
        
            }
        
            public static synchronized SingleTon getInstance() {
                if (singleTon == null) {
                    singleTon = new SingleTon();
                }
                return singleTon;
            }
        }
      

    显然,线程安全问题被解决了,但是其实按照我们上面的分析,只有在第一次创建的时候才会出现线程安全问题,为此将整个代码段都加锁会导致每次调用的时候都是线程同步的,其他线程都是阻塞的,这样显然效率不是很高。

    • 双重校验

        public class SingleTon {
            
            private volatile static SingleTon singleTon;
            
            private SingleTon(){
                
            }
            
            public static SingleTon getInstance(){
                if(singleTon == null){
                    synchronized(SingleTon.class){
                        if(singleTon == null){
                            singleTon = new SingleTon();
                        }
                    }
                }
                return singleTon;
            }
        }
      

    这样就OK了,根据前面的分析,在有可能出现问题的部分加上锁,这样一来不仅能保证线程安全,还能保证效率。

    • 静态内部类
      public class SingleTon {

            private static class SingleTonHolder{
                private static final SingleTon singleTon = new SingleTon();
            }
        
            private SingleTon() {
        
            }
        
            public static SingleTon getInstance() {
                return SingleTonHolder.singleTon;
            }
        }
      
    • 饿汉单例:即类初始化时就实例化

        public class SingleTon {
            
            private static final SingleTon singleTon = new SingleTon();
        
            private SingleTon() {
        
            }
        
            public static SingleTon getInstance() {
                return singleTon;
            }
        }
      

    这样子的话根本不存在线程安全问题了。不过问题就是,一上来就实例化,不管是否使用。

    总结:建议使用双重校验或静态内部类的方式实现。

    优点:对于一些需要不断的创建实例并销毁的情景,单例模式很大程度减少了内存的开支,由于只有一个实例且常驻内存, 减少了系统开销去不断的生成新实例,而且由于只有一个实例,还能避免对资源的多重访问。
    缺点:有一个实例常驻内存,会有一定的系统开销,另外由于单利模式中没有抽象层,因此单例类的扩展有很大的困难。

    相关文章

      网友评论

          本文标题:单例模式

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