一、单例设计模式
一、饿汉式(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 ) |
资源占用 | 可能浪费内存(即使未使用实例) | 按需加载,节省资源 |
性能 | 无同步开销,访问速度快 | 同步方法有性能损耗(可优化为双重检查锁) |
实现复杂度 | 简单 | 较复杂(需处理线程安全) |