目录
[1. 饿汉式(Eager Initialization)](#1. 饿汉式(Eager Initialization))
[2. 懒汉式(Lazy Initialization)](#2. 懒汉式(Lazy Initialization))
[3. 懒汉式 + 同步锁(线程安全)](#3. 懒汉式 + 同步锁(线程安全))
[4. 双重检查锁(Double-Checked Locking)](#4. 双重检查锁(Double-Checked Locking))
[5. 静态内部类(推荐)](#5. 静态内部类(推荐))
[6. 枚举(最佳实践)](#6. 枚举(最佳实践))

单例模式是 Java 中最简单且最常用的设计模式之一,其核心思想是确保一个类只有一个实例,并提供全局访问点。下面分别详解 Java 中的单例模式:
1. 饿汉式(Eager Initialization)
特点 :类加载时立即创建实例,线程安全。
缺点:不支持延迟加载,可能造成资源浪费。
java
public class Singleton {
private static final Singleton INSTANCE = new Singleton();
private Singleton() {} // 私有构造函数
public static Singleton getInstance() {
return INSTANCE;
}
}
2. 懒汉式(Lazy Initialization)
特点 :首次调用时创建实例,支持延迟加载。
缺点:多线程环境下不安全。
java
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) { // 多线程可能同时进入此判断
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
3. 懒汉式 + 同步锁(线程安全)
特点 :通过synchronized
保证线程安全。
缺点:每次调用都加锁,性能开销大。
Dart
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static synchronized Singleton getInstance() { // 方法级同步
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
4. 双重检查锁(Double-Checked Locking)
特点 :线程安全且性能优化,仅首次创建时加锁。
关键点 :使用volatile
关键字禁止指令重排序。
Dart
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;
}
}
5. 静态内部类(推荐)
特点 :线程安全、支持延迟加载,实现简洁。
原理:JVM 保证静态内部类的初始化线程安全。
Dart
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
6. 枚举(最佳实践)
特点 :线程安全、自动支持序列化机制、防止反射攻击。
推荐场景:需要绝对防止单例被破坏的场景。
Dart
public enum Singleton {
INSTANCE;
// 可以添加方法
public void doSomething() {
System.out.println("Singleton method called");
}
}
单例模式的序列化与反序列化问题
如果单例类实现了Serializable
接口,需添加readResolve()
方法防止反序列化时创建新实例:
Dart
private Object readResolve() {
return INSTANCE;
}
单例模式适用场景
- 资源管理器(如数据库连接池、线程池)。
- 配置文件管理。
- 日志记录器。
- GUI 中的窗口管理器。
总结
推荐使用静态内部类 或枚举实现单例模式:
- 静态内部类:简洁、安全、支持延迟加载。
- 枚举:防反射、防序列化攻击,写法优雅。
避免使用普通懒汉式 ,在多线程环境下需使用双重检查锁或更优方案