设计模式一一单例设计模式

一、单例设计模式

一、饿汉式(Eager Initialization)

1. 核心原理

  • 提前初始化:在类加载时(JVM加载类的阶段)直接创建单例实例。
  • 线程安全:依赖类加载机制保证线程安全(JVM保证类加载过程是互斥的)。

2. 代码实现

java 复制代码
public class EagerSingleton {
    // 类加载时直接初始化实例(final确保唯一性)
    private static final EagerSingleton instance = new EagerSingleton();
    
    // 私有构造函数,禁止外部直接new对象
    private EagerSingleton() {}
    
    // 全局访问点
    public static EagerSingleton getInstance() {
        return instance;
    }
}

3. 特点

  • 优点 :
    • 线程安全:无需额外同步代码。
    • 实现简单:代码直观,易于理解。
  • 缺点 :
    • 资源浪费:即使从未使用该实例,也会占用内存。
    • 启动延迟:若初始化过程复杂,可能拖慢程序启动速度。

4. 适用场景

  • 单例对象占用资源少,且程序运行中一定会被使用。
  • 对性能不敏感的场景(例如小型工具类)。

二、懒汉式(Lazy Initialization)

1. 核心原理

  • 延迟初始化 :在第一次调用 getInstance() 时才创建实例。
  • 线程安全需手动保证 :需通过同步机制(如synchronized)防止多线程重复创建。

2. 基础代码实现(线程不安全版本)

java 复制代码
public class LazySingletonUnsafe {
    private static LazySingletonUnsafe instance;
    
    private LazySingletonUnsafe() {}
    
    // 非线程安全:多线程同时调用时可能创建多个实例
    public static LazySingletonUnsafe getInstance() {
        if (instance == null) {
            instance = new LazySingletonUnsafe();
        }
        return instance;
    }
}

3. 线程安全改进(同步方法)

java 复制代码
public class LazySingletonSafe {
    private static LazySingletonSafe instance;
    
    private LazySingletonSafe() {}
    
    // 使用synchronized保证线程安全
    public static synchronized LazySingletonSafe getInstance() {
        if (instance == null) {
            instance = new LazySingletonSafe();
        }
        return instance;
    }
}

4. 特点

  • 优点 :
    • 节省资源:仅在需要时创建实例。
    • 延迟加载:适合初始化耗资源的对象(如数据库连接池)。
  • 缺点 :
    • 同步开销 :每次调用 getInstance() 都需同步,性能较差。
    • 实现复杂:需手动处理线程安全问题。

5. 适用场景

  • 单例对象初始化耗资源或内存。
  • 对性能要求不高,但需要延迟加载的场景。

三、对比总结

对比维度 饿汉式 懒汉式
初始化时机 类加载时立即初始化 第一次调用 getInstance() 时初始化
线程安全 天然线程安全(JVM类加载机制) 需手动同步(如synchronized)
资源占用 可能浪费内存(即使未使用实例) 按需加载,节省资源
性能 无同步开销,访问速度快 同步方法有性能损耗(可优化为双重检查锁)
实现复杂度 简单 较复杂(需处理线程安全)
相关推荐
考虑考虑1 小时前
JDK26中的List.ofLazy()
java·后端·java ee
小蒜学长2 小时前
基于SpringBoot的公寓报修管理系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·公寓报修管理系统·多角色协同
for_ever_love__2 小时前
MySQL 主从复制讲透:binlog 原理、搭建步骤与读写分离
java·数据库·mysql·binlog·读写分离·原理·主从复制
小π军4 小时前
操作系统面试题
java·linux·服务器
倔强的石头1064 小时前
应用账号最小权限实践:读写账号、报表账号、运维账号分层
java·运维·开发语言
Shaoshing5 小时前
ThreadLocal
java·jvm·threadlocal
写后端的胖头鱼5 小时前
一文详解CAS
java·jvm·spring·cas·乐观锁·自旋
鱼宵5 小时前
Spring AI 提示词模板:{变量} 参数化 + few-shot,一条提示词反复用
java·人工智能·spring·few-shot·提示词工程·springai
蜗牛互联网5 小时前
Python消费Responses SSE事件:增量文本、超时与取消
java·开发语言·人工智能·后端·python