程序员设计模式

单例设计模式——我是一条美丽的单身狗

2018-11-26  本文已影响52人  0ur

一只100KG的大菜鸟,正在努力学习中,如有出入,往大佬扶正,谢谢!!!

饿汉式 :

线程安全 ,如果单例用不到 ,造成了内存的开销 .

 public  class HungrySingle {
        private static HungrySingle mHungrySingle = new HungrySingle();

        private HungrySingle() {

        }

        public static HungrySingle getInstance() {
            return mHungrySingle;
        }
    }

懒汉式:

线程不安全的, 在多线程环境下, 并不能做到单例.

    public  class LazybonesSingle {

        private static LazybonesSingle mLazybonesSingle;

        //私有构造
        private LazybonesSingle() {

        }

        //对外提供访问方法
        public  LazybonesSingle getInstance() {
            //如果两个线程同时调永走到 ==null的时候  可能会创建两个对象
            if (mLazybonesSingle == null) {
                mLazybonesSingle = new LazybonesSingle();
            }
            return mLazybonesSingle;
        }

    }

懒汉式:

线程安全 ,获取实例的时候,每次都走同步,造成了不必要的开销.

 public class LazybonesSingleSafe {

        private static LazybonesSingle mLazybonesSingle;

        private LazybonesSingleSafe() {

        }
 
        public synchronized static LazybonesSingle getInstance() {
            if (mLazybonesSingle == null) {
                mLazybonesSingle = new LazybonesSingle();
            }
            return mLazybonesSingle;
        }

    }

DCL(双重锁验证)式:

减少了每次同步的开销 ,还保证了懒加载 ,但是在高并发的情况下,还有可能造成多实例的存在.

public class LazyboneSingleDCL {
        private static volatile LazyboneSingleDCL mLazyboneSingleDCL;

        private LazyboneSingleDCL() {

        }

        public static LazyboneSingleDCL getInstance() {
            //如果为空 进入同步   不等空 直接取走对象  减少了同步的开支
            if (mLazyboneSingleDCL == null) {
                //如果为空 确保只有一个线程进入
                synchronized (LazyboneSingleDCL.class) {
                    //防止多线程 进入 再次判断如果对象不为空 直接取值
                    if (mLazyboneSingleDCL == null) {
                        mLazyboneSingleDCL = new LazyboneSingleDCL();
                    }
                }
            }
            return mLazyboneSingleDCL;
        }
    }

静态内部类式:

java高并发,描述DCL是丑陋的,解决方案是用 静态内部类来解决.
JVM的类加载方式(虚拟机会保证一个类的初始化在多线程环境中被正确的加锁、同步), 来保证了多线程并发访问的正确性.
这种方式是一种比较完美的单例模式. 当然, 它也有其弊端, 依赖特定编程语言, 适用于JAVA平台.

    public class StaticInnerClassForm {
        private StaticInnerClassForm() {

        }

        public static StaticInnerClassForm getInstance() {
            return FormHolder.INSTANCE;
        }

        private static class FormHolder {
            private static StaticInnerClassForm INSTANCE = new StaticInnerClassForm();
        }

    }

以上单例,存在一种情况可以再次创建对象 反序列化 以上方法为了不让序列化创建对象 加入readResolve()方法 可以保证

枚举式:

单例,默认线程安全,任何情况下都保证对象唯一.

 public enum SingletonEnum {

        INSTANCE;

        public void doSomething() {

        }

    }

容器单例式:

android的各种服务的单例使用Map来储存的.

   public class SingleMap {

       private static Map<String, Object> mSingMap = new HashMap<>();

       private SingleMap() {

       }

       public void registerSingleService(String key, Object value) {
           if (!mSingMap.containsKey(key)) {
               mSingMap.put(key, value);
           }
       }

       public Object getService(String key) {
           //如果没有这个值的要抛出异常
           return mSingMap.get(key);

       }
   }

大佬,点个赞再走也不迟,小姐姐正在洗澡~~~

上一篇 下一篇

猜你喜欢

热点阅读