You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解惑:单例模式中饿汉式与懒汉式初始化的时机差异

饿汉式与懒汉式单例的初始化时机差异解析

你觉得两者没有差异的误区,核心在于没搞清楚Java类加载的触发时机不止调用getInstance()这一种情况,这正是两类单例初始化时机的本质区别所在。

1. 饿汉式(EagerSingleton)的初始化逻辑

饿汉式里的静态实例变量是在类加载阶段就完成初始化的:

public class EagerSingleton {
    // 类加载时立即初始化实例
    private static final EagerSingleton instance = new EagerSingleton();

    private EagerSingleton() {}

    public static EagerSingleton getInstance() {
        return instance;
    }
}

根据Java的类加载机制,只要触发类加载的场景出现,这个instance就会被创建,常见的触发场景包括:

  • 首次调用该类的任意静态方法(比如getInstance())
  • 访问该类的任意静态字段(哪怕不是instance)
  • 通过EagerSingleton.class引用类对象(比如反射、类型判断)
  • 初始化该类的子类(如果存在)

也就是说,哪怕你还没调用getInstance(),只要类被加载到JVM中,单例实例就已经存在于内存里了。

2. 懒汉式(LazySingleton)的初始化逻辑

懒汉式的静态实例变量仅声明不初始化,真正的实例创建被延迟到首次调用getInstance()时:

public class LazySingleton {
    // 仅声明静态变量,不立即初始化
    private static LazySingleton instance;

    private LazySingleton() {}

    // 首次调用时才检查并创建实例
    public static synchronized LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

哪怕类已经被加载(比如通过上述的类加载触发场景),只要没调用getInstance(),instance就始终是null,不会执行实例化逻辑。只有当第一次调用getInstance()时,才会完成实例的创建,后续调用直接返回已创建的实例。

3. 实际场景中的差异影响

  • 启动速度:如果单例类初始化需要消耗大量资源(比如加载配置、连接数据库),饿汉式会在程序启动阶段就占用资源,可能拖慢启动速度;懒汉式则把初始化延迟到真正需要的时候,能优化启动性能。
  • 线程安全:饿汉式依赖JVM类加载的线程安全性(类加载过程由JVM保证线程安全),天生不存在多线程问题;懒汉式则需要通过synchronized(或双重检查锁等优化方式)来避免多线程下创建多个实例的问题。

内容的提问来源于stack exchange,提问作者Yu Xing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 00:33:16