单例模式中的饿汉式

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. 简单直接的实现(无需处理同步逻辑)。

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

相关推荐
凌波粒1 小时前
SpringMVC基础教程(1)--MVC/DispathcerServlet
java·spring·mvc
武子康1 小时前
Java-173 Neo4j + Spring Boot 实战:从 Driver 到 Repository 的整合与踩坑
java·数据库·spring boot·后端·spring·nosql·neo4j
凌波粒1 小时前
SpringMVC基础教程(2)--Controller/RestFul风格/JSON/数据转发和重定向
java·后端·spring·json·restful
老鼠只爱大米2 小时前
Java 设计模式之适配器模式:系统集成的万能接口
java·设计模式·适配器模式·adapter·java设计模式
一叶飘零_sweeeet2 小时前
Java+EasyExcel 打造学习平台视频学习时长统计系统
java·报表·easyexcel
Go away, devil2 小时前
Java-----集合
java·开发语言
JIngJaneIL2 小时前
旅游|内蒙古景点旅游|基于Springboot+Vue的内蒙古景点旅游管理系统设计与实现(源码+数据库+文档)
java·vue.js·spring boot·论文·旅游·毕设·内蒙古景点旅游
新之助小锅3 小时前
java版连接汇川PLC,发送数据,读取数据,保持重新链接,适用安卓
android·java·python
VBA63374 小时前
VBA即用型代码手册:利用函数保存为PDF文件UseFunctionSaveAsPDF
开发语言