美文网首页
单例模式

单例模式

作者: 要学的东西太多了 | 来源:发表于2018-10-30 17:44 被阅读0次

    单例模式,保证全局只有一个实例,分为以下几种方式实现:

    1.饿汉式,缺点,创建出来后不管用不用,内存里面都占用空间:

    public class Single {
        private static Single single= new Single();
    
        private Single() {
        }
        
        public static Single getInstance(){
            return single;
        }
    }
    

    2.懒汉式,缺点是每次都要判断,且需要同步,有一定的时间花费:

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

    3.双重加锁机制,被volatile修饰的变量的值,JVM会强制将线程本地内存的变量刷新到共享主内存,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,否则两个线程同时获取对象,A创建了对象,但很可能出现对象还没刷新到主内存的情况,B去判断的时候还是空的,又去创建了一个对象。且它能禁止指令重排序优化,从而确保多个线程能正确的处理该变量。考虑一种情况,在多线程下,使用下面这种方式来获取对象,未重排序的对象创建顺序是:分配内存地址→初始化实例对象→将对象指向分配的内存地址,如果重排序导致后面两步反过来,线程A执行了1、3,还没执行第2步,线程B通过下面的方法去拿对象判断到不为空,直接返了一个未初始化的对象,这时候用这个对象来执行操作就会出错:

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

    4.类级内部类,不使用就不会加载:

    public class Single {
    
        private Single() {
        }
        
        public static class SingleInner{
            private static Single single = new Single();
        }
    
        public static Single getInstance(){
            return SingleInner.single;
        }
    }
    

    5.枚举,如果对内存泄漏有一定要求的话,尽量不要使用这种方式。

    6.为防止通过反射调用私有构造器生成对象,判断对象不为空的时候抛出异常。

    7.要防止序列化反序列化拿到新的对象,要添加一个readResolve方法。

    相关文章

      网友评论

          本文标题:单例模式

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