周振林 周振林
首页
  • 前端文章

    • HTML
    • CSS
    • Tailwind CSS (opens new window)
    • JavaScript
    • Vue3
    • 其他
  • Spring
  • SpringMVC
  • Mybatis
  • Docker
  • 设计模式
  • 机器视觉
  • 安装教程
  • 其他教程
  • 基础
  • 虚拟化
  • OpenStack
  • 心情杂货
关于
收藏

周振林

IT界的小学生
首页
  • 前端文章

    • HTML
    • CSS
    • Tailwind CSS (opens new window)
    • JavaScript
    • Vue3
    • 其他
  • Spring
  • SpringMVC
  • Mybatis
  • Docker
  • 设计模式
  • 机器视觉
  • 安装教程
  • 其他教程
  • 基础
  • 虚拟化
  • OpenStack
  • 心情杂货
关于
收藏
  • Spring

  • SpringMVC

  • Mybatis

  • Docker

  • 设计模式

    • 单例模式
      • 单例模式
        • 实际应用场景
      • 创建方式
        • 饿汉式
        • 懒汉式
        • 静态内部类(最优)
    • 工厂设计模式
    • 策略模式
  • 机器视觉

  • 安装教程

  • 其他教程

  • 后端
  • 设计模式
周振林
2026-03-18
目录

单例模式

# 单例模式

单例模式是最常用的设计模式之一,核心目标是保证一个类在整个程序生命周期中只有一个实例,并提供一个全局访问点来获取这个实例。

# 实际应用场景

  1. 数据库连接池
  • 创建数据库连接(TCP 握手、认证)是非常耗时的操作,如果每次操作数据库都 new 一个连接池,会导致连接数爆炸、性能暴跌;单例能保证整个应用只有一个连接池,统一管理连接的创建、复用、销毁。
  • 例如:Java 中的DruidDataSource、HikariCP连接池,默认都是单例模式实现,全局只初始化一次连接池配置。
  1. 缓存管理:
  • 缓存需要全局唯一的实例,否则不同实例的缓存数据不一致,会出现 “读不到最新数据”、“重复缓存相同内容” 的问题;单例能统一缓存的增删改查逻辑。
  • 例如Spring 中的CacheManager、Redis 的JedisPool/LettuceClient,都是单例模式 —— 整个应用只有一个缓存客户端实例,所有业务代码都通过这个实例操作缓存。
  1. 日志工具类
  • 日志工具需要保证日志写入的顺序(比如按时间戳写入文件),如果多个日志实例同时写入一个文件,会出现日志错乱、内容重叠;单例能保证日志操作的串行化。
  • 例如:Log4j、SLF4J、Python 的 logging 模块,默认都是单例模式 —— 全局只有一个日志器(Logger)实例,所有代码都通过这个实例输出日志。

# 创建方式

# 饿汉式

线程安全,简单但可能浪费资源

public class SingletonHungry {
    // 1. 私有静态实例(类加载时直接初始化,唯一实例)
    private static final SingletonHungry INSTANCE = new SingletonHungry();
    
    // 2. 私有构造方法,禁止外部new
    private SingletonHungry() {}
    
    // 3. 公共静态方法,返回唯一实例
    public static SingletonHungry getInstance() {
        return INSTANCE;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12

# 懒汉式

推荐:懒加载 + 线程安全 + 高性能
只有调用 getInstance() 时才创建实例(懒加载),但多线程环境下可能创建多个实例,需加锁。

public class SingletonDCL {
    // 1. 私有静态实例,加volatile防止指令重排序
    private static volatile SingletonDCL instance;
    
    // 2. 私有构造方法
    private SingletonDCL() {}
    
    // 3. 双重检查锁
    public static SingletonDCL getInstance() {
        // 第一次检查:实例已存在则直接返回,避免加锁开销
        if (instance == null) {
            synchronized (SingletonDCL.class) {
                // 第二次检查:防止多线程同时进入第一层检查后,重复创建实例
                if (instance == null) {
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# 静态内部类(最优)

最优:懒加载 + 线程安全 + 无锁
利用 JVM 类加载机制保证线程安全,且只有调用 getInstance() 时才加载内部类、创建实例。

public class SingletonStaticInner {
    // 1. 私有构造方法
    private SingletonStaticInner() {}
    
    // 2. 静态内部类(仅在被使用时加载)
    private static class SingletonHolder {
        private static final SingletonStaticInner INSTANCE = new SingletonStaticInner();
    }
    
    // 3. 公共静态方法
    public static SingletonStaticInner getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Last Updated: 2026/03/18, 21:53:17
Docker运行JAR
工厂设计模式

← Docker运行JAR 工厂设计模式→

最近更新
01
卷积神经网络原理
03-18
02
工厂设计模式
03-18
03
PaddleX实现垃圾分类
03-16
更多文章>
Theme by Vdoing | Copyright © 2019-2026 鲁ICP备19032096号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×