单例模式中的饿汉式

1. 饿汉式单例完整代码(基础版)

java 复制代码
// 饿汉式单例:类加载时就创建实例
public class EagerSingleton {
    // 关键点1:静态私有变量,类加载时初始化实例
    // static:属于类,全局唯一;final:确保实例不可被替换;private:禁止外部直接访问
    private static final EagerSingleton INSTANCE = new EagerSingleton();

    // 关键点2:私有化构造器,阻止外部通过new创建实例
    private EagerSingleton() {
        // 可以在构造器中添加初始化逻辑(如初始化资源)
        System.out.println("饿汉式单例实例被创建了");
    }

    // 关键点3:公开静态方法,提供全局访问点
    public static EagerSingleton getInstance() {
        return INSTANCE; // 直接返回预创建的实例
    }

    // 测试方法:验证实例唯一性
    public void doSomething() {
        System.out.println("当前实例地址:" + this);
    }

    // 主方法测试
    public static void main(String[] args) {
        // 尝试创建多个实例
        EagerSingleton s1 = EagerSingleton.getInstance();
        EagerSingleton s2 = EagerSingleton.getInstance();

        // 调用方法,观察实例地址是否相同
        s1.doSomething(); // 输出:当前实例地址:EagerSingleton@xxxxxxx
        s2.doSomething(); // 输出:当前实例地址:EagerSingleton@xxxxxxx(与s1相同)

        // 验证:s1和s2是否为同一个对象
        System.out.println("s1 == s2 ? " + (s1 == s2)); // 输出:true(证明唯一)
    }
}

2. 运行结果解析

  • 程序启动时,EagerSingleton类加载,会立即执行new EagerSingleton(),打印 "饿汉式单例实例被创建了"(类加载阶段初始化)。
  • 调用getInstance()两次,返回的s1s2地址完全相同(==结果为true),证明全局只有一个实例。
  • 无法通过new EagerSingleton()创建实例(构造器私有,编译报错),确保了实例唯一性。

3. 多线程环境下的线程安全测试

饿汉式天生线程安全,因为类加载过程由 JVM 保证同步,以下代码验证:

java 复制代码
public class EagerSingletonThreadTest {
    public static void main(String[] args) {
        // 启动10个线程,同时获取实例
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                EagerSingleton instance = EagerSingleton.getInstance();
                System.out.println("线程" + Thread.currentThread().getId() + "获取的实例:" + instance);
            }).start();
        }
    }
}

运行结果:所有线程打印的实例地址完全相同,证明多线程环境下不会创建多个实例(线程安全)。

4. 饿汉式的局限性示例(资源浪费场景)

如果单例实例初始化成本高(如加载大文件),但程序可能用不到,会浪费资源:

java 复制代码
public class ResourceHeavyEagerSingleton {
    // 假设初始化需要加载100MB的配置文件(模拟高成本)
    private static final ResourceHeavyEagerSingleton INSTANCE = new ResourceHeavyEagerSingleton();

    private ResourceHeavyEagerSingleton() {
        System.out.println("加载100MB配置文件...(耗时操作)");
    }

    public static ResourceHeavyEagerSingleton getInstance() {
        return INSTANCE;
    }

    public static void main(String[] args) {
        System.out.println("程序启动,但暂时不需要用这个单例...");
        // 此时,即使没调用getInstance(),实例也已创建并加载了资源(浪费)
    }
}

运行结果:程序启动后,会直接打印 "加载 100MB 配置文件...(耗时操作)",即使从未使用该实例,资源已被消耗。

总结

饿汉式单例通过类加载时初始化静态实例 + 私有构造器 + 静态访问方法的组合,实现了:

  1. 实例唯一性(禁止外部创建,全局仅一个);
  2. 线程安全性(JVM 类加载机制保证);
  3. 简单直接的实现(无需处理同步逻辑)。

但需注意:如果实例初始化成本高且可能不被使用,会造成资源浪费,这种场景下需考虑懒汉式等其他实现。

相关推荐
Scott9999HH1 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔1 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社2 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海2 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖3 小时前
JDK 26 新特性详解
java·开发语言
马优晨4 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区6 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大6 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai6 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
维天说7 小时前
CLI-Switch 2026年3月版历史设计:Hook、TTY 隔离与 JSON 状态
java·服务器·json