美文网首页
单例模式 之 写法大全

单例模式 之 写法大全

作者: 程就人生 | 来源:发表于2022-02-05 15:35 被阅读0次

单例模式不仅仅是面试官最爱考核的内容之一,也是程序员们在实际开发中经常用到的设计模式之一,所以它是我们的必备技能之一。说到单例模式,你能想到哪些问题呢?

  1. 单例模式的特点,请说说?

  2. 单例模式,主要有哪些应用场景,你还记得吗?

  3. 单例模式有哪些写法,你还记得多少?

  4. 单例模式是线程安全的吗?

先上一张思维导图:

图片

单例模式:是一种创建型模式,不为别人创建对象,只为自己创建对象,以提供一个全局的唯一的对象实例。这个全局是指在一个容器里的全局。一个启动的项目只保持一个该对象的实例。

使用场景:生产唯一序列号,Web里的计算器,还要其他比较消耗资源的开销,比如数据库连接池,I/O操作等等。

缺点:没有接口,不能继承,与单一职责原则冲突。

背诵再多概念,也不及敲上一段代码。

1. 单例模式 之 懒汉模式一,线程不安全;

/**
 * 懒汉式 ,线程不安全
 * 延迟加载
 * @author 程就人生
 * @Date 2022/1/25
 */
public class Singleton {  
  
  /**
   * 静态的实例变量,实例化后不会被改变
   */
    private static Singleton instance;  
    
    /**
     * 私有的构造函数
     */
    private Singleton (){}  
  
    /**
     * 没加同步锁,不支持多线程,线程不安全
     * @return
     */
    public static Singleton getInstance() {  
      // 延迟加载
      if (instance == null) {  
          instance = new Singleton();  
      }  
      return instance;  
    }  
}
图片

懒汉模式有两种,一种是线程不安全的,一种是线程安全的。

2. 单例模式 之 懒汉模式二,线程安全;

该实现方式,增加了同步锁,但会对性能有影响。

/**
 * 懒汉式 ,线程安全
 * 延迟加载
 * @author 程就人生
 * @Date
 */
public class Singleton {  
  
  /**
   * 静态的实例变量,实例化后不会被改变
   */
    private static Singleton instance; 
    
    /**
     * 私有的构造函数
     */
    private Singleton (){}  
    
    /**
     * 使用了synchronized 关键字,线程安全,支持多线程
     * @return
     */
    public static synchronized Singleton getInstance() {  
      // 延迟加载
      if (instance == null) {  
          instance = new Singleton();  
      }  
      return instance;  
    }  
}

3. 单例模式 之 饿汉模式一;

图片
/**
 * 饿汉式 1
 * 线程安全,非延迟加载
 * 不管是否使用,先进行了实例化,所以称之为饿汉式
 * @author 程就人生
 * @Date 2022/1/25
 */
public class Singleton {  

  /**
   * 先静态,后动态
   * 先属性,后方法
   * 先上后下
   */
    private static Singleton instance = new Singleton();  
    
    /**
     * 私有的构造函数
     */
    private Singleton (){}  
    
    /**
     * 直接返回
     * @return
     */
    public static Singleton getInstance() {  
      return instance;  
    }  
}

4. 单例模式 之 饿汉模式二;

/**
 * 饿汉式 静态块单例模式
 * 线程安全,非延迟加载
 * @author 程就人生
 * @Date 2022/1/25
 */
public class Singleton{
  private static final Singleton instance;
  /**
   * 静态代码块,公共内存区域
   */
  static {
    instance = new Singleton();
  }
  /**
   * 私有的构造函数
   */
  private Singleton (){}  
    
  /**
   * 直接返回
   * @return
   */
  public static Singleton getInstance() {  
     return instance;  
  }    
}

5. 单例模式 之 双检锁/双重校验锁 (DCL double-checked locking)

该实现方式,是对懒汉安全模式的升级,提高了性能。

图片
/**
 * 双检锁/双重校验锁 (DCL double-checked locking)
 * 线程安全,延迟加载
 * @author 程就人生
 * @Date 2022/1/25
 */
public class Singleton {  
  
  /**
   * 静态的实例变量,实例化后不会被改变
   * 还使用了 volatile 关键字
   */
    private volatile static Singleton singleton; 
    
    /**
     * 私有的构造函数
     */
    private Singleton (){}  
    
    /**
     * 在获取实例的方法内部使用了同步锁
     * 同步锁是在getInstance方法内,阻塞发生在getInstance方法上,而不是类上;
     * 业务逻辑不复杂,用户感知不到
     * @return
     */
    public static Singleton getInstance() {  
      if (singleton == null) {  
          synchronized (Singleton.class) {  
          if (singleton == null) {  
            // new一个对象做的三件事
            // 1.分配内存给对象
            // 2.初始化对象
            // 3.设置singleton指向刚分配的内存地址
              singleton = new Singleton();  
          }  
          }  
      }  
      return singleton;  
    }  
}

6. 单例模式 之 登记式/静态内部类;

该实现方式,是对 双检锁/双重校验锁 方式的升级;兼顾了饿汉式单例模式的内存浪费和同步锁的性能问题。

图片

/**
 * 登记式/静态内部类
 * 线程安全,延迟加载
 * 兼顾饿汉单例模式的内存浪费问题和同步的性能问题
 * @author 程就人生
 * @Date 2022/1/25
 */
public class Singleton {  
    
    /**
     * 私有的构造函数
     * 使用Singleton的时候,默认会先初始化内部类
     */
    private Singleton (){}  
    
    /**
     * 获取实例
     * static 使单例的空间共享,保证这个方法不会被重写、重载
     * @return
     */
    public static final Singleton getInstance() {  
      // 返回结果以前,一定会先调用加载内部类
      return SingletonHolder.INSTANCE;  
    }  
    
    /**
   * 静态内部类,默认不加载
   */
    private static class SingletonHolder {  
      private static final Singleton INSTANCE = new Singleton();  
    }  
}

7. 单例模式 之 枚举式;

大师们都推崇的写法,最简易的写法。

图片

/**
 * 枚举式
 * 线程安全,非延迟加载
 * @author 程就人生
 * @Date 2022/1/25
 */
public enum Singleton { 
  
    INSTANCE;  
  
  public static Singleton getInstance() {  
      return INSTANCE;  
    }
}

这些单例模式真的是安全的吗,口说无凭,来一个简单的多线程验证一下吧:

/**
 * 一个简单的多线程
 * 用多线程测试单例模式的线程安全
 * @author 程就人生
 * @Date
 */
class Thread1 extends Thread{
  // 线程名称
  private String name;
  
    public Thread1(String name) {
       this.name=name;
    }
  public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(name + "运行  :  " + i);
            // 输出单例模式对象的地址

            System.out.println(Singleton.getInstance().toString());
            try {
              //随机休眠
                sleep((int) Math.random() * 10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }       
  }
}

在main方法里调用;

public static void main(String[] argo){    
    Thread1 mTh1=new Thread1("A");
    Thread1 mTh2=new Thread1("B");
    mTh1.start();
    mTh2.start();
} 
  1. 单例模式 之 懒汉模式一,线程不安全,测试结果:

A运行  :  0
B运行  :  0
com.example.Singleton@b9098ae
com.example.Singleton@12b0f150
B运行  :  1
com.example.Singleton@b9098ae
B运行  :  2
com.example.Singleton@b9098ae
A运行  :  1
com.example.Singleton@b9098ae
A运行  :  2
com.example.Singleton@b9098ae

第二个地址和其他地址不一样,没有实现实例单一,因此是线程不安全的。

2. 单例模式 之 懒汉模式二,线程安全,测试结果:

A运行  :  0
B运行  :  0
com.example.Singleton@790d3283
com.example.Singleton@790d3283
B运行  :  1
A运行  :  1
com.example.Singleton@790d3283
A运行  :  2
com.example.Singleton@790d3283
com.example.Singleton@790d3283
B运行  :  2
com.example.Singleton@790d3283

查看输出的实例地址都是一样的,保证了单一实例,因此是线程安全的。

其他的就不一一验证了,请读者自行验证。

相关文章

  • 设计模式之单例模式详解

    设计模式之单例模式详解 单例模式写法大全,也许有你不知道的写法 导航 引言 什么是单例? 单例模式作用 单例模式的...

  • 单例模式 之 写法大全

    单例模式不仅仅是面试官最爱考核的内容之一,也是程序员们在实际开发中经常用到的设计模式之一,所以它是我们的必备技能之...

  • 单例模式

    JAVA设计模式之单例模式 十种常用的设计模式 概念: java中单例模式是一种常见的设计模式,单例模式的写法...

  • Unity3d游戏开发之-单例设计模式- 单例模式二:多线程二(

    单例模式4:多线程二(双重锁定)这种双重锁定考虑了线程安全,是正规写法 游戏常用设计模式之单例设计模式的写法大概常...

  • 第03条 用私有构造方法或者枚举类型强化Singleton属性

    单例模式最佳写法1 - 双重校验锁 单例模式最佳写法2 - 静态内部类

  • 单例模式

    单例模式的写法

  • iOS 单例模式

    关于单例模式的详解,看完这几篇,就完全了然了。iOS 单例模式iOS中的单例模式iOS单例的写法

  • Kotlin中的单例模式与Java对比

    目前java中的单例模式有多种写法,kotlin中的写法更多一点,本篇会总结全部的到单例模式写法。 一、懒人写法(...

  • 单例模式

    一、介绍 二、单例模式代码实现 三、单例的简介写法

  • java 24 设计模式

    单例模式java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例、饿汉式单例、...

网友评论

      本文标题:单例模式 之 写法大全

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