推荐使用的两种单例模式-学习总结篇

本文是对单例模式的学习总结。介绍了DCL单例,其优点是按需初始化、线程安全,缺点是首次加载慢、可能因Java内存模型失效。还提到静态内部类单例模式,能保证线程安全、单例唯一且延迟实例化,是推荐方式。

    学习设计模式-单例模式自我总结 给自己看的方便记忆。

 1.Double Check Lock(DCL) 单例

   DCL 方式实现单例模式的优点是既能够在需要时才初始化单例,又能保证线程安全,且单例对象初始化后调用getInstance不进行同步锁。

public class Singleton {

    private static Singleton mInstance=null;
    private  Singleton(){}

    public static Singleton getInstance(){
        if (mInstance==null){
            synchronized (Singleton.class){
                if (mInstance==null){
                    mInstance=new Singleton();
                }
            }
        }
        return mInstance;
    }
}

   这里解释一下两次判空:第一层判断主要是为了避免不比要的同步,第二层的判断是为了在null的情况下创建实例。

(1)给Singleton的实例分配内存;

(2)调用Singleton()的构造函数,初始化成员字段;

(3)将mInstance对象指向分配的空间(此时mInstance就不是null了);

具体原因是因为 JDK1.5之前 Java编译器允许处理器乱序执行 上面的第二跟第三的顺序是无法保证的。也就是说,执行顺序可能是1-2-3也可能是1-3-2. 如果是后者顺序颠倒 线程会直接取走mInstance 在使用就会出错,这就是DCL失效问题,而且这种错误难以跟踪难以重现 。

优缺点:

DCL的优点:资源利用率高,第一次执行getInstance时单例对象才会被实例化 效率高。

DCL的缺点:第一次加载时反应稍慢,也由于Java内存模型的原因偶尔会失败。在高并发环境下也有一定的缺陷,虽然发生概率很小。

DCL模式是使用最多的单例实现方式,它能在需要时才实例化单例对象,并且能够在绝大多数场景下保证单例对象的唯一性,除非你的代码在并发场景比较复杂或者低于JDK1.6版本下使用,否则这种方式一般能够满足需求。

2.静态内部类单例模式

 DCL虽然在一定程度上解决了资源消耗、多余的同步、线程安全等问题,但是它还是在某些情况下出现失效的问题。这个问题被称为双重检查锁定(DCL)失效,在《Java并发编程实践》一书的最后谈到了这个问题,并指出这种“优化”是丑陋的,不赞成使用。

public class Singleton {

    private Singleton(){}

    public static Singleton getInstance(){
        return SignletonHolder.mInstance;
    }
    /**
    *  静态内部类
    */

    private static class SignletonHolder{
        private static  final Singleton mInstance=new Singleton();
    }
}

当第一次加载Singleton类时并不会初始化mInstance,只有在在第一调用Signleton的getInstance方法是才会导致mInstance被初始化。因此,第一次调用getInstance方法会导致虚拟机加载SingletonHolder类,这种方法不仅能保证线程安全,也能保证单例对象的唯一性,同时也延迟了单例的实例化,所以这是推荐使用的单例模式实现方式。

当然还有一些其他的单例模式 如:枚举单例、使用容器实现单例 这里不做解释。

PS:以上知识点来源于观看的《Android源码设计模式》一书 书写博客为自己总结 方便自己观看 不喜勿喷。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值