三分钟认识单例模式

1.什么是单例模式

​ 在单例模式下,一个类只能有一个实例对象。

2.什么场景需要使用单例模式

  • 需要频繁实例化然后销毁的对象。
  • 创建对象时耗时过多或者耗资源过多,但又经常用到的对象。
  • 有状态的工具类对象。
  • 频繁访问数据库或文件的对象。

具体工作场景举例

  • 计数器
  • 应用程序日志
  • 数据库连接池/多线程的线程池

2.单例模式的实现思路及方式

  • 饿汉模式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.example.demo.other;

/**
* @className: ESingleTest
* @description: 饿汉实现单例模式
* @author: diane
* @date: 2021/10/11
**/
public class ESingleTest {
// 缺点:占内存
public ESingleTest(){}
// 刚开始先初始化一个实例
private static ESingleTest instance = new ESingleTest();
// 需要的时候直接取
public static ESingleTest getInstance(){
return instance;
}
}
  • 懒汉模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    package com.example.demo.other;

    /**
    * @className: LSingleTest
    * @description: 懒汉实现单例模式
    * @author: diane
    * @date: 2021/10/11
    **/
    public class LSingleTest {
    public LSingleTest(){}
    // 创建一个null的实例
    private static LSingleTest instance = null;

    // 懒汉
    // 缺点:方法上加锁,慢
    public synchronized static LSingleTest getInstance(){
    //当多线程都取到instance为null时,这里单例就蚌埠住了
    if (instance == null){
    instance = new LSingleTest(); // 需要的时候再创建
    }
    return instance;
    }

    // 进化版懒汉(双检锁)
    // 把方法上的锁拿进去了。
    public static LSingleTest getInstancePlus(){
    if (instance == null){ // 一检
    synchronized (LSingleTest.class){ // 二检
    if (instance == null){
    instance = new LSingleTest();
    }
    }
    }
    return instance;
    }
    }

    • 总结

      正常来说,使用饿汉单例即可,遇到内存瓶颈需要优化的时候再去考虑双检锁实现单例。