设计模式之单例模式

Posted 杨哲丶

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式之单例模式相关的知识,希望对你有一定的参考价值。

上篇我们讲述了单例模式的基本概念 , 并且我们也说了饿汉式,懒汉式,线程安全懒汉式 , 但是则三种写法都还不是我推崇的写法 , 今天我们继续说剩下的三种写法 : Dcl写法 ,内部类写法, 枚举式写法 , 其实也可以一篇写完的 , 但是分个章节可以过渡一下 , 这样也可以让我们休息片刻 , 就想电视剧广告更精彩 !

那我们开始 , Let’s Go !

DCL单例模式

DCL 的意思是什么 ? 为什么叫 DCL , 其实就是 Double Check Lock 的简称 , 我们直接看代码 :

public class DclSingleton 
    //volatile 保证了原子模型,创建类的步骤顺序不变,指令重排序优化
    private static  volatile DclSingleton sDclSingleton = null;

    private DclSingleton() 
    

    public static DclSingleton getInstance() 
        //避免不必要的同步请求
        if (null == sDclSingleton) 
            //保持同步
            synchronized (DclSingleton.class) 
                //类的初始化操作
                if (null == sDclSingleton) 
                    sDclSingleton=new DclSingleton();
                
            
        
        return sDclSingleton;
    

这里重点解释一下 , 为什么需要多做一次 null == sDclSingleton 的判断 , 就像注释里边的分析一样 , 因为下边我们用同步代码块进行的同步的操作 , 所以我们在他之前可以进行仅一步的空判断 , 避免不必要的同步请求 .

然后我还需要解释一下为什么对 sDclSingleton 还需要多加一个 volatile 的字段来修饰呢 ? 这个我们可以从类的加载机制来解释 , 第一步 sDclSingleton 需要在方法区中存在一个索引 , 第二步 new DclSingleton(); 的操作的时候我们首先要在堆分配一块控件 , 第三步是将堆中的变量指向索引 , 但是 Jvm 有这么一个缺点 , 在线程不安全的情况下 , 在即时编辑器中存在指令重排序优化 , 导致我们上述所说的步骤可能第三步骤在第二步之前 , 第二步在第一步之前 , 所以也会导致线程不安全 , 我们设置 volative 这个字段就是保持变量的原子性 , 禁止即时编辑器中存在指令重排序优化 , 从而解决线程不安全问题 .

内部类写法

在上边介绍的DCL模式 , 已经解决了进一步的解决了不必要的同步请求 , 但是写法上还是不简单 , 这里我们来介绍一个能满足 延时加载 , 线程安全 , 性能优越 , 写法简单的需求 , 这种写法就是内部类写法 , 如果别人问到你单例模式的写法 , 我推荐用这种写法可以省下不少的说辞.

public class InnerClassSingeton 

    private InnerClassSingeton() 
    

    private static InnerClassSingeton getInstance() 
        return HolderInner.Instance;
    

    private static class HolderInner 
        public static final InnerClassSingeton Instance = new InnerClassSingeton();
    

因为Jvm的本身的机制 static final 修饰的变量能保证唯一性 , 而且静态内部类没有外部方法调用getInstance()方法的时候 , 不会使用内部类 , 保证了延时加载 , 另外我们没有用同步锁的来保证线程安全 ,性能有很大的提升. 所以我推荐这种写法.

枚举类写法

枚举是利用他本身的一个实例 , 这中写法简单 , 但是可能用的少 , 但是需要注意的一点是不能在写额外的获得实例方法 , 这样就不能保证线程的安全了 , 不能再用你Java本身自带的属性了.

public enum EnumSingleton 
    //定义一个元素,他就是EnumSingleton的一个实例
    INSTANCE;

以上是关于设计模式之单例模式的主要内容,如果未能解决你的问题,请参考以下文章

设计模式之单例模式

JAVA设计模式之单例模式(转)

JAVA设计模式之单例模式

设计模式之单例模式

单例模式之单例模式

设计模式之单例模式