美文网首页
单例模式-讲解

单例模式-讲解

作者: cao苗子 | 来源:发表于2019-10-24 15:26 被阅读0次

    什么是单列模式?
    百度百科:单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)。

    1.懒汉式

    /**
     * created by panshimu
     * on 2019/10/24
     *  懒汉式-单列模式
     */
    public class Single01 {
        public static Single01 mSingle01;
        private Single01(){
        }
        /**
         * 存在多线程并发问题 可能会存在多个实列
         * @return
         */
        public static Single01 getInstance(){
            if(mSingle01 == null){
                mSingle01 = new Single01();
            }
            return mSingle01;
        }
    }
    

    2.饿汉式

    /**
     * created by panshimu
     * on 2019/10/24
     * 饿汉式-单列模式
     */
    public class Single02 {
        //随着类的加载就创建对象
        public static Single02 mSingle02 = new Single02();
        private Single02(){
        }
        public static Single02 getInstance(){
            return mSingle02;
        }
    }
    
    

    3.线程安全

    /**
     * created by panshimu
     * on 2019/10/24
     */
    public class Single05 {
        public static Single05 mSingle05;
        private Single05(){
        }
    
        /**
         * 加同步锁 能解决同步问题 但是会影响效率 因为每一次都要加锁的判断
         * @return
         */
        public static synchronized Single05 getInstance(){
            if(mSingle05 == null){
                mSingle05 = new Single05();
            }
            return mSingle05;
        }
    }
    

    4.线程和效率

    /**
     * created by panshimu
     * on 2019/10/24
     */
    public class Single06 {
    
        //防止重排序 线程可见
        public static volatile Single06 mSingle06;
        private Single06(){
        }
    
        /**
         * 既保证线程安全 效率也还是比较高的
         * @return
         */
        public static Single06 getInstance(){
            if(mSingle06 == null){
                synchronized (Single06.class){
                    if(mSingle06 == null){
                        mSingle06 = new Single06();
                    }
                }
            }
            return mSingle06;
        }
    }
    

    第四种 单列模式中 既保证了线程的安全 又提高了效率,但是还是存在问题的。
    比如 线程的不可性,重排序问题。在多线程的情况下。

    线程的可见行:某一个线程中改变了某一个公共对象或是公共变量,短时间内可能会存在在某一个线程是不可见的,意思就是在某一个线程中这个值可以还是原来的值。因为每一个线程都有自己的缓存区。

    看下面的列子:

    public static void main(String[] args){
            VolatileThread volatileThread = new VolatileThread();
            new Thread(volatileThread).start();
            while (true){
                if(volatileThread.isFlag()){
                    System.out.println("00000000000000000000");
                    break;
                }
            }
        }
        static class VolatileThread implements Runnable{
            private boolean flag = false;
            @Override
            public void run() {
                try{
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                flag = true;
                System.out.println("flag="+flag);
            }
            public boolean isFlag(){
                return flag;
            }
        }
    

    执行上面的列子,发现 System.out.println("00000000000000000000"); 并没有执行,实际上 flag=true 了。但是 volatileThread.isFlag() 返回的还是 false 所以说短时间内 值还没有被改变。
    怎么解决这个问题呢?
    只需要给 flag 变量加上 volatile 关键字 就可以了。

    在4中把改为

     public static volatile Single05 mSingle05;
    

    就可以了。

    5.静态内部类

    保证线程的安全 用到的时候才会new

    /**
     * created by panshimu
     * on 2019/10/24
     * 静态内部类
     */
    public class Single04 {
        private Single04(){
        }
        public static Single04 getInstance(){
            return Single04Holder.mSingle04;
        }
        public static class Single04Holder{
            private static volatile Single04 mSingle04 = new Single04();
        }
    }
    

    6.容器管理

    /**
     * created by panshimu
     * on 2019/10/24
     *  容器管理
     */
    public class Single07 {
        private static Map<String,Object> mSingleMap = new HashMap<>();
        private Single07(){
        }
        static {
            mSingleMap.put("miaozi",new Single07());
        }
    
        public static Object getInstance(String str){
            return mSingleMap.get(str);
        }
    }
    

    好了 ,单列模式就到这里啦。

    相关文章

      网友评论

          本文标题:单例模式-讲解

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