单例模式什么时候用饿汉什么时候用懒汉

单例模式中饿汉式与懒汉式的选择,核心取决于实例的初始化成本、是否必然被使用、线程安全需求 以及是否依赖外部资源 。两者的核心区别是:饿汉式"预加载"(类加载时初始化),懒汉式"懒加载"(首次使用时初始化),具体适用场景如下:

一、饿汉式(立即初始化):适合"实例必用、初始化轻量"的场景

饿汉式在类加载时就创建单例实例,代码简单且天然线程安全(JVM保证类加载过程是线程安全的)。

适用场景:

  1. 实例初始化成本低 (如无复杂计算、无IO操作、占用资源少)

    例如:工具类单例(如日志工具、字符串处理工具),初始化仅需简单赋值或无状态,提前加载不会造成资源浪费。

  2. 实例必然会被使用

    若单例是系统核心组件(如全局配置管理器、连接池管理器),启动后一定会被调用,此时"预加载"反而能避免首次使用时的延迟,提升响应速度。

  3. 不依赖外部动态资源

    饿汉式初始化在类加载阶段执行,若实例创建依赖外部参数(如配置文件、数据库连接信息),而这些参数在类加载时还未就绪(如Spring的@Value注入晚于类加载),会导致初始化失败。因此,无外部依赖的单例更适合饿汉式。

二、懒汉式(延迟初始化):适合"实例可能不用、初始化 heavy"的场景

懒汉式在首次调用getInstance()时才初始化实例,避免了资源的无效占用,但需要额外处理线程安全问题(如双重检查锁定)。

适用场景:

  1. 实例初始化成本高 (如需要加载大数据、连接数据库、启动耗时任务)

    例如:报表生成引擎、大模型客户端实例(初始化需加载模型权重),若这些实例可能永远不会被某些用户/场景触发,懒汉式可避免启动时的资源浪费(内存、CPU)。

  2. 实例可能不被使用

    若单例是"可选功能"的核心组件(如某个仅管理员可用的数据分析模块),大部分场景下用不到,懒汉式的"按需加载"能减少系统启动负担。

  3. 依赖外部动态资源

    若实例创建依赖 runtime 动态参数(如从配置中心拉取的地址、用户登录后获取的令牌),这些参数在类加载时还未获取,只能通过懒汉式在参数就绪后再初始化。

三、关键对比与决策依据

维度 饿汉式 懒汉式
初始化时机 类加载时 首次使用时
线程安全 天然安全(JVM保证) 需手动处理(如双重检查锁定)
资源占用 启动即占用,可能浪费 按需占用,更节省
首次调用性能 无延迟(已初始化) 有延迟(首次初始化耗时)
外部依赖兼容性 差(依赖需在类加载前就绪) 好(依赖就绪后再初始化)

总结

  • 用饿汉式:当单例"必被使用、初始化轻量、无外部依赖"时,优先选饿汉式------简单、安全、无延迟。
  • 用懒汉式:当单例"可能不用、初始化 heavy、依赖动态资源"时,选懒汉式------节省资源、适配复杂依赖,但需注意线程安全实现。

(例如:项目中的全局日志工具类适合饿汉式;而对接第三方AI接口的客户端实例(初始化需API密钥,且可能仅部分功能用到)适合懒汉式。)

相关推荐
重生之我是Java开发战士16 天前
【Java SE】多线程(三):单例模式,阻塞队列,线程池与定时器
java·javascript·单例模式
许彰午18 天前
34_Java设计模式之单例模式
java·单例模式·设计模式
罗超驿19 天前
10.Java单例模式全解析:饿汉式与懒汉式实现及线程安全深度剖析
安全·单例模式·javaee
布朗克16820 天前
33 设计模式精讲
java·单例模式·设计模式
雨浓YN20 天前
基于设计模式的Winform软件框架-01Xml\Log\Ini日志(单例模式+生产者消费者模式)
单例模式·设计模式
仙俊红20 天前
Java 单例模式:类里面为什么可以有自己类型的字段?
java·开发语言·单例模式
swordbob21 天前
prototype 注入到 singleton 里,prototype是否还是线程安全的
安全·spring·单例模式·原型模式
谁似人间西林客22 天前
工业大数据实战:看中国智造如何用数据驱动效率革命
大数据·单例模式
张小姐的猫23 天前
【Linux】多线程 —— 线程池 | 单例模式 | 常见锁
linux·运维·服务器·c++·单例模式·设计模式·策略模式
Java面试题总结24 天前
双重检验锁的单例模式在高并发下的可见性问题
单例模式