• 初探设计模式-单例模式


    这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

    • 单例类只有一个实例

    • 单例类必须自己创建自己的唯一实例

    • 单例类必须给其他对象提供这一实例

    • 构造函数私有

    public class SingleObject {
     
       //创建 SingleObject 的一个对象
       private static SingleObject instance = new SingleObject();
     
       //让构造函数为 private,这样该类就不会被实例化
       private SingleObject(){}
     
       //获取唯一可用的对象
       public static SingleObject getInstance(){
          return instance;
       }
     
       public void showMessage(){
          System.out.println("Hello World!");
       }
    }
    • 懒汉式实现方式

      • 线程不安全

    public class Singleton {  
        private static Singleton instance;  
        private Singleton (){}  
      
        public static Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
        }  
    }
    • 线程安全的懒汉式

    public class Singleton {  
        private static Singleton instance;  
        private Singleton (){}  
        public static synchronized Singleton getInstance() {  
        if (instance == null) {  
            instance = new Singleton();  
        }  
        return instance;  
        }  
    }
    • 饿汉式实现方式

      • 不是懒加载

      • 线程安全

      • 基于classloader机制避免了多线程的同步问题,不过,instance在类装载时就实例化。

      public class Singleton{
          private static Singleton instance = new Singleton();
          private Singleton(){}
          public static Singleton getInstance(){
              return instance;
          }
      }
    • 双重校验锁

      • 懒加载

      • 线程安全

      public class Singleton{
          private volatile static Singleton instance;
          private Singleton(){}
          public static Singleton getInstance(){
              if(instance == null){
                  synchronized(this.class){
                      if(instance == null)
                          instance = new Singleton();
                  }
              }
              return instance;
          }
      }
      • 问题:为什么需要两次判断if(instance==null)?

        分析:第一次校验:由于单例模式只需要创建一次实例,如果后面再次调用getInstance方法时,则直接返回之前创建的实例,因此大部分时间不需要执行同步方法里面的代码,大大提高了性能。如果不加第一次校验的话,那跟上面的懒汉模式没什么区别,每次都要去竞争锁。

             第二次校验:如果没有第二次校验,假设线程t1执行了第一次校验后,判断为null,这时t2也获取了CPU执行权,也执行了第一次校验,判断也为null。接下来t2获得锁,创建实例。这时t1又获得CPU执行权,由于之前已经进行了第一次校验,结果为null(不会再次判断),获得锁后,直接创建实例。结果就会导致创建多个实例。所以需要在同步代码里面进行第二次校验,如果实例为空,则进行创建。

  • 相关阅读:
    ASP.NET Core WebAPI学习-4
    PIESDKDoNet二次开发配置注意事项
    PIE SDK影像快速拼接
    PIE SDK加载WMS服务数据
    PIE SDK加载自定义服务数据
    PIE SDK 距离分类和最大似然分类
    PIE SDK矢量点生成等值线、面
    PIE SDK与OpenCV结合说明文档
    C#录制声卡声音喇叭声音音箱声音
    C#录制屏幕采集系统桌面画面
  • 原文地址:https://www.cnblogs.com/Duancf/p/14130604.html
Copyright © 2020-2023  润新知