2023 05 31 设计模式之单例模式
Contents
什么是单例模式
单例模式(Singleton Pattern)是最常用的设计模式之一,它保证一个类只有一个实例,并提供一个全局访问点。
在实际开发中,单例模式常用于:
- 数据库连接池
- 线程池
- 配置管理器
- 日志记录器
实现方式
1. 饿汉式(线程安全)
类加载时就立即创建实例,由JVM保证线程安全。
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {}
public static Singleton getInstance() {
return INSTANCE;
}
}
优点:实现简单,无线程安全问题
缺点:类加载时就创建,可能造成内存浪费
2. 懒汉式(线程不安全)
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
缺点:线程不安全,多线程下可能创建多个实例
3. 懒汉式 + synchronized(线程安全)
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
缺点:每次调用都要同步,性能较差
4. 双重检查锁(推荐)
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
注意:必须使用 volatile 关键字,防止指令重排
5. 静态内部类(推荐)
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
优点:延迟加载,线程安全,推荐使用
6. 枚举方式(最佳)
public enum Singleton {
INSTANCE;
public void doSomething() {
// 业务逻辑
}
}
优点:
- 写法简洁
- 线程安全
- 防止反射攻击
- 防止反序列化重新创建对象
对比总结
| 方式 | 线程安全 | 延迟加载 | 防止反射 | 防止反序列化 |
|---|---|---|---|---|
| 饿汉式 | ✅ | ❌ | ❌ | ❌ |
| 懒汉式 | ❌ | ✅ | ❌ | ❌ |
| synchronized | ✅ | ✅ | ❌ | ❌ |
| 双重检查锁 | ✅ | ✅ | ❌ | ❌ |
| 静态内部类 | ✅ | ✅ | ❌ | ❌ |
| 枚举 | ✅ | ❌ | ✅ | ✅ |
实际应用
在Spring框架中,Bean的默认作用域就是单例(Singleton),容器启动时创建所有单例Bean。
@Component
public class MyBean {
// 默认是单例作用域
}
如果需要多例,可以使用 @Scope("prototype") 注解。
总结
- 简单场景推荐使用静态内部类或枚举
- 需要延迟加载时选择双重检查锁或静态内部类
- 需要防止反射和反序列化时使用枚举
- Spring等框架已经内置了单例管理,无需手动实现