• 单例模式


    单例

      1.饿汉式单例

        优点:没有加锁,执行效率更高

             缺点:类加载的时候就初始化,不管用否都占着空间,如果项目中存在大量的单例对象,则会浪费内存空间

        

      2.懒汉式单例

        优点:被外部类调用时,内部才会加载

        

          存在线程安全,当有多个线程同时访问时,返回多个实例,违反了单例对象原则

        

         添加了synchronized关键字,当有大量线程同时访问时,cpu分配压力上升,造成阻塞,造成性能下降

        

         双重检查锁 

        这里的写法将同步放在了方法里面的第一个非空判断之后,这样可以确保对象不为空的时候不会被阻塞,但是第二个非空判断的意义是什么呢?我们假设线程A首先获得锁,进入了第3行,还没有释放锁的时候,线程B又进来了,这时候因为线程还没有执行对象初    始化,所以判空成立,会进入第2行等待获得锁,这时候当线程A释放锁之后,线程B会进入到第3行,这时候因为第二个判空判断对象不为空了,所以就会直接返回,如果没有第2个判空,这时候就会产生新的对象了,所以需要两次判空!

    大家可能注意到这里的变量定义上加了volatile关键字,为什么呢?这是因为DCL在可能会存在失效的情况:
    第4行代码:lazySingleton = new LazyDoubleCheckSingleton();
    大致存在以下三步:
    (1)、分配内存给对象
    (2)、初始化对象
    (3)、将初始化好的对象和内存地址建立关联(赋值)
    而这3步由于CPU指令重排序,不能保证一定按顺序执行,假如线程A正在执行new的操作,第1步和第3步都执行完了,但是第2步还没执行完,这时候线程B进入到方法中的第1行代码,判空不成立,所以直接返回了对象,而这时候对象并没有初始化完全,所以就会报错了,解决这个问题的办法就是使用volatile关键字,禁止指令重排序(jdk1.5之后),保证按顺序执行上面的三个步骤

        

         使用了内部类的特性,LazyHolder里面的内容等到外面调用时才执行,可以被反射或者序列化破坏单例

        

        

         

      3.注册式单例

        注册式单例是将所有的对象保存到某一个地方,通过唯一的标识符获取对应的单例对象

        

         

           4.ThreadLacal式单例

        ThreadLacal不能保证创建对象的全局唯一性,但是可以保证单个线程中对象的唯一性

        

         

  • 相关阅读:
    js和css
    主题
    php.ini
    css 选择器、元素默认宽度、media screen
    linux 重要笔记
    cookie和session、
    tp5 报 A non well formed numeric value encountered 的错解决办法
    pdo
    二叉树
    顺序串
  • 原文地址:https://www.cnblogs.com/wanglu1991/p/15684508.html
Copyright © 2020-2023  润新知