zoukankan      html  css  js  c++  java
  • 设计模式——单例模式

      定义:

        保证一个类只有一个实例,并提供一个访问它的全局访问点。

      实现:

        1. 将构造方法私有化。外部不能通过构造方法来实例化一个对象,只能通过静态方法来获得该类的唯一实例。

        2. 定义一个私有类的静态变量。(静态方法不能访问非静态成员变量,所以定义一个静态变量)

        3. 提供一个共有的获取实例的静态方法。

      好处:

        单例模式的特点是单例类在应用程序中只被实例化一次,以保证外界访问的都是同一个对象。避免了多次创建的问题,节省系统资源,加快对象的访问速度。

      缺点:

        不适于变化的对象,没有抽象层不利于扩展。

      五种书写单例模式方式:

    1. 懒汉式    

      在第一次使用时候才进行初始化,有线程安全问题,达到懒加载效果。 添加关键字 synchronized 保证线程安全。防止多线程中A和B同时进入instance没有初始化 创建两个实例。每次获取实例都要进行同步,因此效率低。

      public class Singleton01 {
          // 定义一个私有类的静态变量
          private static Singleton01 instance;
          // 私有化构造函数
          private Singleton01() {}
          // 提供一个共有的获取实例的静态方法
          public static synchronized Singleton01 getInstance() {
              if (instance == null) {
                  instance = new Singleton01();
              }
              return instance;
          }
      }

          总结:线程安全(添加了synchronized 关键字) 、 懒加载 (执行时才初始化)、效率低(每次都要进行同步)    

    2. 饿汉式

      加载时候就初始化,没有线程安全问题,效率高、没有懒加载,如果该实例没有被使用过,会造成内存浪费。

      public class Singleton02 {
          // 定义一个私有类的静态变量并初始化
          private static Singleton02 instance = new Singleton02();
          // 私有化构造函数
          private Singleton02() {}
          // 提供一个共有的获取实例的静态方法
          public static Singleton02 getInstance() {
              return instance;
          }
      }

          总结:线程安全(不存在线程问题)、非懒加载、 效率高

    3. 双重监测机制(DCL)

      只有使用时,才进行初始化,达到懒加载效果、只有在初始化时候才会进行加锁、没有线程问题、也不会影响效率。

      public class Singleton03 {
          // volatile 使每次使用都从主存中取而不是工作内存中获取
          private static volatile Singleton03 instance;
          // 私有化构造函数
          private Singleton03() {};
          // 提供一个共有的获取实例的静态方法
          public static Singleton03 getInstance() {
              if(instance == null) {
                  // 如果instance等于空 则同步(加锁)
                  // 只能有一个线程得到资源执行。另一个线程等待当前线程执行完才能执行该代码块。
                  // 只有初始化的时候为空 所有只加锁一次
                  synchronized (Singleton03.class) {
                      // 第二次进行判断
                      if(instance == null) {
                          instance = new Singleton03();
                      }
                  }
              }
              return instance;
          }
      }

           总结:线程安全(初始化时加锁)、懒加载、效率高

    4. 静态内部类(延迟初始化占位类)

      只有使用时候,调用静态内部类进行初始化、达到懒加载效果。没有线程问题(类变量的赋值语句,在编译生成字节码的时候写在<clinit>()中,初始化单线程调用<clinit>()完成变量的赋值)、效率高。

      public class Singleton04 {
          // 定义一个静态内部类用来初始化静态变量
          private static class SingletonHolder{
              private static final Singleton04 instance = new Singleton04();
          }
          // 私有化构造函数
          private Singleton04() {}
          // 提供一个共有的获取实例的静态方法
          public static Singleton04 getInstance() {
              return SingletonHolder.instance;
          }
      }

          总结:线程安全、懒加载、效率高

    5. 枚举

      枚举线程安全只会装载一次,线程安全。不会被反射破坏单利。

      public class Singleton05 {
          // 私有化构造函数
          private Singleton05() {};
          // 枚举类型
          private enum SingletonEnum{
              INSTANCE;
              // 私有化成员变量
              private final Singleton05 instance;
              // 构造函数
              SingletonEnum(){
                  instance = new Singleton05();
              }
              // 私有化方法
              private Singleton05 getInstance() {
                  return instance;
              }
          }
          // 提供一个共有的获取实例的静态方法
          public static Singleton05 getInstance() {
              return SingletonEnum.INSTANCE.getInstance();
          }
      }

          总结:线程安全、懒加载、效率高

        

  • 相关阅读:
    springboot 和 spring clould 的版本匹配问题
    行到水穷处,坐看云起时!
    转: 从单体应用 -> SOA--> 微服务 ,服务治理 [熔断,限流,降级,服务恢复,服务容错,监控等等]---> RPC ---> 下一代技术[Service Mesh]
    spring-boot自定义线程池
    千与千寻的内容抓手
    哲学三问
    简约的人生
    关于中间件整理
    此心光明,亦复何言!
    能容的下你身边比你优秀的人---是一种修行
  • 原文地址:https://www.cnblogs.com/liljoker/p/12964785.html
Copyright © 2011-2022 走看看