单例模式中的饿汉式

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()两次,返回的s1和s2地址完全相同(==结果为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. 简单直接的实现(无需处理同步逻辑)。

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

相关推荐
1024奇点7 小时前
【仓颉语言入门 · 第二篇 第 22 课】
开发语言·ide·开源
Warren2Lynch8 小时前
C4 模型详解:利用 Visual Paradigm 可视化软件架构的综合指南
开发语言·uml
天河归来8 小时前
第三方接口不稳定,如何让核心任务继续完成
java·大数据
Knight_AL8 小时前
Java 文件下载时文件名中的 `#` 被转换成 `%23`?一次 URL 编码与解码问题排查
java·开发语言
FRing039 小时前
vue2干货总结2(v-bind、v-for、v-model、指令修饰符、v-bind操作class和style)
开发语言·前端·vue.js·vue2
by2099910 小时前
C++ 智能指针的所有权与使用
开发语言·c++·经验分享
砚底藏山河10 小时前
python量化自定义周期 K 线合成
java·开发语言·数据库·python·金融
IT召唤狮10 小时前
开源企业级零信任项目Pangolin,零信任能挡住PHP核弹漏洞吗?
开发语言·开源·php
知已难寻10 小时前
03 · OpenStack的计算管理 Nova
运维·服务器·开发语言·云原生·云计算·openstack·开源软件
Rover Ramble10 小时前
C++ 用互斥锁实现读写锁
开发语言·c++