一、单例模式核心概念
1.1 定义
单例模式确保一个类只有一个实例,并提供一个全局访问点来访问这个唯一实例。
1.2 核心要素
- 私有构造器:防止外部通过new创建实例
- 静态实例变量:保存唯一实例
- 静态访问方法:提供全局访问点
- 线程安全机制:多线程环境下保证唯一性
二、Java实现方式详解
2.1 饿汉式(Eager Initialization)
csharp
/**
* 饿汉式 - 类加载时初始化
* 优点:线程安全,实现简单
* 缺点:浪费资源,无论是否使用都会创建实例
*/
class EagerSingleton {
// 静态常量,类加载时初始化
private static final EagerSingleton INSTANCE = new EagerSingleton();
// 私有构造器
private EagerSingleton() {
// 防止反射攻击
if (INSTANCE != null) {
throw new RuntimeException("禁止通过反射创建实例");
}
System.out.println("EagerSingleton 实例被创建");
}
// 全局访问点
public static EagerSingleton getInstance() {
return INSTANCE;
}
// 防止反序列化破坏单例
protected Object readResolve() {
return INSTANCE;
}
}
适用场景:
- 实例创建成本低
- 应用启动时就需要使用的实例
- 线程池、数据库连接池等资源
2.2 懒汉式(Lazy Initialization)
csharp
import java.util.concurrent.atomic.AtomicReference;
/**
* 懒汉式 - 延迟加载
* 演变过程:非线程安全 → 方法同步 → 双重检查锁 → 静态内部类 → 枚举
*/
class LazySingleton {
// 版本1:非线程安全(不推荐)
static class Version1 {
private static Version1 instance;
private Version1() {}
public static Version1 getInstance() {
if (instance == null) {
instance = new Version1(); // 多线程下可能创建多个实例
}
return instance;
}
}
// 版本2:方法同步(效率低)
static class Version2 {
private static Version2 instance;
private Version2() {}
public static synchronized Version2 getInstance() {
if (instance == null) {
instance = new Version2();
}
return instance;
}
}
// 版本3:双重检查锁(DCL)
static class Version3 {
// volatile禁止指令重排序,确保可见性
private static volatile Version3 instance;
private Version3() {
// 防止指令重排序导致的初始化问题
}
public static Version3 getInstance() {
if (instance == null) { // 第一次检查,避免不必要的同步
synchronized (Version3.class) {
if (instance == null) { // 第二次检查,确保线程安全
instance = new Version3();
// 对象创建的三步:
// 1. 分配内存空间
// 2. 初始化对象
// 3. 将引用指向内存地址
// volatile防止步骤2和3重排序
}
}
}
return instance;
}
}
// 版本4:静态内部类(推荐)
static class Version4 {
private Version4() {}
// 静态内部类在第一次使用时加载
private static class SingletonHolder {
private static final Version4 INSTANCE = new Version4();
static {
System.out.println("SingletonHolder 类被加载");
}
}
public static Version4 getInstance() {
return SingletonHolder.INSTANCE;
}
}
// 版本5:CAS实现(无锁)
static class Version5 {
private static final AtomicReference<Version5> INSTANCE =
new AtomicReference<>();
private Version5() {}
public static Version5 getInstance() {
for (;;) {
Version5 current = INSTANCE.get();
if (current != null) {
return current;
}
current = new Version5();
if (INSTANCE.compareAndSet(null, current)) {
return current;
}
// CAS失败,说明其他线程已经创建实例,继续循环获取
}
}
}
}
2.3 枚举式(Joshua Bloch推荐)
arduino
/**
* 枚举单例 - Effective Java推荐
* 优点:绝对防止多次实例化,防止反射和序列化攻击
*/
enum EnumSingleton {
INSTANCE;
// 可以添加实例变量和方法
private String config = "default";
private int counter = 0;
// 枚举的构造器是私有的
EnumSingleton() {
System.out.println("EnumSingleton 初始化");
}
public void doSomething() {
counter++;
System.out.println("执行操作,计数:" + counter);
}
public String getConfig() {
return config;
}
public void setConfig(String config) {
this.config = config;
}
// 枚举单例的优势:
// 1. 防止反射攻击:反射不能创建枚举实例
// 2. 防止序列化攻击:枚举的序列化机制保证唯一性
// 3. 线程安全:枚举实例的创建是线程安全的
// 4. 简洁明了:代码最简洁
}
2.4 线程内单例(ThreadLocal)
csharp
/**
* ThreadLocal单例 - 每个线程独立的单例
* 应用场景:ThreadLocal变量,数据库连接,Session管理
*/
class ThreadLocalSingleton {
private static final ThreadLocal<ThreadLocalSingleton> THREAD_LOCAL_INSTANCE =
ThreadLocal.withInitial(() -> {
System.out.println(Thread.currentThread().getName() + " 创建 ThreadLocalSingleton");
return new ThreadLocalSingleton();
});
private ThreadLocalSingleton() {}
public static ThreadLocalSingleton getInstance() {
return THREAD_LOCAL_INSTANCE.get();
}
public void remove() {
THREAD_LOCAL_INSTANCE.remove();
}
// 实例变量,每个线程独立
private final ThreadLocal<String> threadData = new ThreadLocal<>();
public void setThreadData(String data) {
threadData.set(data);
}
public String getThreadData() {
return threadData.get();
}
}
2.5 登记式单例(Registry Singleton)
typescript
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 登记式单例 - Spring IoC容器风格
* 应用场景:管理多个单例对象
*/
class RegistrySingleton {
// 单例注册表
private static final Map<String, Object> SINGLETON_REGISTRY =
new ConcurrentHashMap<>();
private RegistrySingleton() {}
/**
* 注册单例
*/
public static void registerSingleton(String name, Object singleton) {
synchronized (SINGLETON_REGISTRY) {
if (!SINGLETON_REGISTRY.containsKey(name)) {
SINGLETON_REGISTRY.put(name, singleton);
}
}
}
/**
* 获取单例
*/
@SuppressWarnings("unchecked")
public static <T> T getSingleton(String name) {
return (T) SINGLETON_REGISTRY.get(name);
}
/**
* 按类型获取单例,不存在则创建
*/
@SuppressWarnings("unchecked")
public static <T> T getSingleton(Class<T> clazz) {
String className = clazz.getName();
Object singleton = SINGLETON_REGISTRY.get(className);
if (singleton == null) {
synchronized (clazz) {
singleton = SINGLETON_REGISTRY.get(className);
if (singleton == null) {
try {
singleton = clazz.getDeclaredConstructor().newInstance();
SINGLETON_REGISTRY.put(className, singleton);
} catch (Exception e) {
throw new RuntimeException("创建单例失败: " + className, e);
}
}
}
}
return (T) singleton;
}
/**
* 获取所有单例
*/
public static Map<String, Object> getAllSingletons() {
return new ConcurrentHashMap<>(SINGLETON_REGISTRY);
}
/**
* 销毁单例
*/
public static void destroySingleton(String name) {
synchronized (SINGLETON_REGISTRY) {
Object singleton = SINGLETON_REGISTRY.remove(name);
if (singleton instanceof AutoCloseable) {
try {
((AutoCloseable) singleton).close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
三、应用场景(详细分类)
3.1 系统级单例
3.1.1 配置管理器
arduino
/**
* 配置管理器 - 系统配置统一管理
*/
class ConfigManager {
private static final ConfigManager INSTANCE = new ConfigManager();
private final Properties config = new Properties();
private volatile long lastModified = 0;
private final File configFile;
private ConfigManager() {
configFile = new File("application.properties");
loadConfig();
startConfigWatcher();
}
public static ConfigManager getInstance() {
return INSTANCE;
}
private void loadConfig() {
try (FileInputStream fis = new FileInputStream(configFile)) {
config.load(fis);
lastModified = configFile.lastModified();
System.out.println("配置文件加载完成");
} catch (IOException e) {
throw new RuntimeException("加载配置文件失败", e);
}
}
private void startConfigWatcher() {
Thread watcher = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Thread.sleep(5000); // 每5秒检查一次
if (configFile.lastModified() > lastModified) {
loadConfig();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
watcher.setDaemon(true);
watcher.start();
}
public String getProperty(String key) {
return config.getProperty(key);
}
public String getProperty(String key, String defaultValue) {
return config.getProperty(key, defaultValue);
}
public int getIntProperty(String key, int defaultValue) {
String value = getProperty(key);
if (value != null) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
// 忽略格式错误
}
}
return defaultValue;
}
}
3.1.2 资源池管理器
java
/**
* 数据库连接池管理器
*/
class ConnectionPoolManager {
private static volatile ConnectionPoolManager instance;
private final List<Connection> pool = new ArrayList<>();
private final int maxSize = 10;
private final String url = "jdbc:mysql://localhost:3306/test";
private final String username = "root";
private final String password = "password";
private ConnectionPoolManager() {
initializePool();
}
public static ConnectionPoolManager getInstance() {
if (instance == null) {
synchronized (ConnectionPoolManager.class) {
if (instance == null) {
instance = new ConnectionPoolManager();
}
}
}
return instance;
}
private void initializePool() {
for (int i = 0; i < maxSize; i++) {
try {
Connection conn = DriverManager.getConnection(url, username, password);
pool.add(conn);
} catch (SQLException e) {
throw new RuntimeException("创建数据库连接失败", e);
}
}
}
public synchronized Connection getConnection() throws SQLException {
if (pool.isEmpty()) {
// 池为空,创建新连接
return DriverManager.getConnection(url, username, password);
}
return pool.remove(pool.size() - 1);
}
public synchronized void releaseConnection(Connection conn) {
if (pool.size() < maxSize) {
pool.add(conn);
} else {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public synchronized void closeAllConnections() {
for (Connection conn : pool) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
pool.clear();
}
}
3.2 业务级单例
3.2.1 缓存管理器
typescript
/**
* 本地缓存管理器
* 应用场景:热点数据缓存,减少数据库访问
*/
class CacheManager {
private static final CacheManager INSTANCE = new CacheManager();
private final Map<String, CacheEntry> cache = new ConcurrentHashMap<>();
private final ScheduledExecutorService cleaner = Executors.newScheduledThreadPool(1);
private CacheManager() {
// 定期清理过期缓存
cleaner.scheduleAtFixedRate(this::cleanExpiredEntries, 1, 1, TimeUnit.MINUTES);
}
public static CacheManager getInstance() {
return INSTANCE;
}
public void put(String key, Object value, long ttlSeconds) {
long expiryTime = System.currentTimeMillis() + ttlSeconds * 1000;
cache.put(key, new CacheEntry(value, expiryTime));
}
public Object get(String key) {
CacheEntry entry = cache.get(key);
if (entry == null) {
return null;
}
if (entry.isExpired()) {
cache.remove(key);
return null;
}
return entry.value;
}
public void remove(String key) {
cache.remove(key);
}
public void clear() {
cache.clear();
}
public int size() {
return cache.size();
}
private void cleanExpiredEntries() {
Iterator<Map.Entry<String, CacheEntry>> it = cache.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, CacheEntry> entry = it.next();
if (entry.getValue().isExpired()) {
it.remove();
}
}
}
// 缓存条目
private static class CacheEntry {
final Object value;
final long expiryTime;
CacheEntry(Object value, long expiryTime) {
this.value = value;
this.expiryTime = expiryTime;
}
boolean isExpired() {
return System.currentTimeMillis() > expiryTime;
}
}
}
3.2.2 序列号生成器
ini
/**
* 分布式序列号生成器(雪花算法简化版)
* 应用场景:分布式ID生成,订单号生成
*/
class SequenceGenerator {
private static final SequenceGenerator INSTANCE = new SequenceGenerator();
// 雪花算法参数
private final long workerId; // 工作机器ID
private final long datacenterId; // 数据中心ID
private long sequence = 0L; // 序列号
private long lastTimestamp = -1L; // 上次时间戳
// 起始时间戳(2024-01-01)
private final long twepoch = 1704067200000L;
// 位分配
private final long workerIdBits = 5L; // 5位工作机器ID
private final long datacenterIdBits = 5L; // 5位数据中心ID
private final long sequenceBits = 12L; // 12位序列号
// 最大值
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
// 移位
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private SequenceGenerator() {
// 从系统环境或配置读取
this.workerId = Long.parseLong(System.getProperty("worker.id", "1"));
this.datacenterId = Long.parseLong(System.getProperty("datacenter.id", "1"));
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException("workerId 超出范围");
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException("datacenterId 超出范围");
}
}
public static SequenceGenerator getInstance() {
return INSTANCE;
}
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException("时钟回退,拒绝生成ID");
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
// 批量生成ID
public synchronized List<Long> batchNextId(int count) {
List<Long> ids = new ArrayList<>(count);
for (int i = 0; i < count; i++) {
ids.add(nextId());
}
return ids;
}
}
3.3 框架级单例
3.3.1 Spring风格的Bean容器
typescript
/**
* 简化版Spring Bean容器
* 管理单例Bean的生命周期
*/
class BeanContainer {
private static final BeanContainer INSTANCE = new BeanContainer();
// Bean注册表
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>();
private final Map<String, Class<?>> beanDefinitions = new ConcurrentHashMap<>();
private final List<BeanPostProcessor> beanPostProcessors = new ArrayList<>();
private BeanContainer() {
// 初始化容器
registerBeanPostProcessors();
}
public static BeanContainer getInstance() {
return INSTANCE;
}
/**
* 注册Bean定义
*/
public void registerBeanDefinition(String beanName, Class<?> beanClass) {
beanDefinitions.put(beanName, beanClass);
}
/**
* 获取Bean
*/
@SuppressWarnings("unchecked")
public <T> T getBean(String beanName) {
// 从单例池获取
Object bean = singletonObjects.get(beanName);
if (bean != null) {
return (T) bean;
}
// 创建新的单例
synchronized (singletonObjects) {
bean = singletonObjects.get(beanName);
if (bean == null) {
Class<?> beanClass = beanDefinitions.get(beanName);
if (beanClass == null) {
throw new RuntimeException("未找到Bean定义: " + beanName);
}
try {
// 创建实例
bean = beanClass.getDeclaredConstructor().newInstance();
// Bean后处理器 - 初始化前
for (BeanPostProcessor processor : beanPostProcessors) {
bean = processor.postProcessBeforeInitialization(bean, beanName);
}
// 调用初始化方法
if (bean instanceof InitializingBean) {
((InitializingBean) bean).afterPropertiesSet();
}
// Bean后处理器 - 初始化后
for (BeanPostProcessor processor : beanPostProcessors) {
bean = processor.postProcessAfterInitialization(bean, beanName);
}
// 放入单例池
singletonObjects.put(beanName, bean);
} catch (Exception e) {
throw new RuntimeException("创建Bean失败: " + beanName, e);
}
}
}
return (T) bean;
}
/**
* 按类型获取Bean
*/
public <T> T getBean(Class<T> requiredType) {
for (Map.Entry<String, Object> entry : singletonObjects.entrySet()) {
if (requiredType.isInstance(entry.getValue())) {
return requiredType.cast(entry.getValue());
}
}
// 从定义中查找
for (Map.Entry<String, Class<?>> entry : beanDefinitions.entrySet()) {
if (requiredType.isAssignableFrom(entry.getValue())) {
return getBean(entry.getKey());
}
}
throw new RuntimeException("未找到类型为 " + requiredType.getName() + " 的Bean");
}
private void registerBeanPostProcessors() {
// 这里可以扫描类路径,自动发现BeanPostProcessor
// 简化实现:手动添加
beanPostProcessors.add(new AutowiredAnnotationBeanPostProcessor());
}
/**
* 销毁容器
*/
public void destroy() {
for (Object bean : singletonObjects.values()) {
if (bean instanceof DisposableBean) {
try {
((DisposableBean) bean).destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
singletonObjects.clear();
beanDefinitions.clear();
}
// 相关接口
interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
interface DisposableBean {
void destroy() throws Exception;
}
interface BeanPostProcessor {
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
static class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {
// 实现自动注入逻辑
}
}
四、优缺点深度分析
4.1 优点(详细分析)
4.1.1 资源优化
-
内存效率
- 减少重复对象创建
- 降低JVM堆内存压力
- 减少GC频率和停顿时间
- 提高缓存命中率
-
性能提升
- 避免重复初始化开销
- 减少系统调用(如文件IO、网络IO)
- 提高响应速度
- 降低CPU使用率
-
资源共享
- 连接池共享数据库连接
- 线程池重用线程资源
- 缓存共享热点数据
- 配置信息全局共享
4.1.2 系统设计
-
访问控制
- 统一入口,便于权限控制
- 集中管理,便于监控
- 操作审计,便于追踪
- 资源限制,防止滥用
-
状态一致性
- 保证全局状态一致
- 避免数据不一致问题
- 简化状态同步逻辑
- 提高系统稳定性
-
架构简化
- 减少类间耦合
- 简化依赖关系
- 提高代码可读性
- 降低维护成本
4.1.3 业务价值
-
成本控制
- 减少服务器资源消耗
- 降低数据库连接成本
- 减少外部API调用次数
- 提高硬件利用率
-
可靠性
- 避免资源泄漏
- 防止内存溢出
- 保证服务可用性
- 提高系统容错性
4.2 缺点(详细分析)
4.2.1 设计问题
-
违反设计原则
- 违反单一职责原则:既要管业务又要管实例
- 违反开闭原则:扩展困难
- 违反依赖倒置原则:依赖具体实现
- 违反接口隔离原则:接口臃肿
-
测试困难
csharp// 难以测试的单例 class HardToTestSingleton { private static HardToTestSingleton instance; private HardToTestSingleton() { // 复杂的初始化逻辑 loadConfig(); initCache(); startThreads(); } public static HardToTestSingleton getInstance() { if (instance == null) { instance = new HardToTestSingleton(); } return instance; } public void doBusiness() { // 业务逻辑依赖于全局状态 } } // 测试困难 class TestClass { @Test public void testBusiness() { // 单例状态会影响其他测试 // 无法隔离测试 HardToTestSingleton.getInstance().doBusiness(); } } -
依赖隐藏
- 隐式依赖难以发现
- 依赖关系不明确
- 增加理解成本
- 导致循环依赖
4.2.2 实现问题
-
线程安全复杂
- 双重检查锁实现复杂
- volatile关键字理解困难
- 指令重排序问题
- 内存可见性问题
-
序列化攻击
java// 易受序列化攻击的单例 class VulnerableSingleton implements Serializable { private static VulnerableSingleton instance = new VulnerableSingleton(); private VulnerableSingleton() {} public static VulnerableSingleton getInstance() { return instance; } // 缺少readResolve方法,会被序列化攻击 } // 攻击代码 class SerializationAttack { public static void main(String[] args) throws Exception { VulnerableSingleton instance1 = VulnerableSingleton.getInstance(); // 序列化 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(instance1); // 反序列化 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); VulnerableSingleton instance2 = (VulnerableSingleton) ois.readObject(); System.out.println(instance1 == instance2); // false! } } -
反射攻击
csharp// 易受反射攻击的单例 class ReflectionVulnerableSingleton { private static ReflectionVulnerableSingleton instance = new ReflectionVulnerableSingleton(); private ReflectionVulnerableSingleton() {} public static ReflectionVulnerableSingleton getInstance() { return instance; } } // 攻击代码 class ReflectionAttack { public static void main(String[] args) throws Exception { ReflectionVulnerableSingleton instance1 = ReflectionVulnerableSingleton.getInstance(); // 通过反射创建新实例 Constructor<ReflectionVulnerableSingleton> constructor = ReflectionVulnerableSingleton.class.getDeclaredConstructor(); constructor.setAccessible(true); ReflectionVulnerableSingleton instance2 = constructor.newInstance(); System.out.println(instance1 == instance2); // false! } }
4.2.3 运行时问题
-
内存泄漏
arduinoclass MemoryLeakSingleton { private static MemoryLeakSingleton instance; private final Map<String, byte[]> cache = new HashMap<>(); private MemoryLeakSingleton() {} public static MemoryLeakSingleton getInstance() { if (instance == null) { instance = new MemoryLeakSingleton(); } return instance; } public void cacheData(String key, byte[] data) { cache.put(key, data); // 可能积累大量数据 } // 缺少清理方法 } -
性能瓶颈
- 锁竞争导致性能下降
- 单点故障风险
- 扩展性受限
- 难以水平扩展
-
生命周期管理
- 初始化时机难以控制
- 销毁时机不明确
- 资源清理困难
- 异常处理复杂
五、使用要点(最佳实践)
5.1 选择策略
arduino
/**
* 单例模式选择决策树
*/
class SingletonSelection {
/**
* 根据需求选择单例实现
*/
public static String selectSingletonImplementation(Requirements req) {
if (req.isPreventReflectionAttack() && req.isPreventSerializationAttack()) {
return "使用枚举单例"; // 最安全
}
if (req.isLazyInitialization()) {
if (req.isHighPerformance()) {
if (req.isThreadSafe()) {
return "使用双重检查锁"; // 高性能线程安全
} else {
return "使用CAS单例"; // 无锁高性能
}
} else {
return "使用静态内部类"; // 延迟加载,简单安全
}
} else {
if (req.isSimpleImplementation()) {
return "使用饿汉式"; // 最简单
} else {
return "使用枚举单例"; // 推荐默认
}
}
}
static class Requirements {
boolean lazyInitialization; // 是否需要延迟加载
boolean threadSafe; // 是否需要线程安全
boolean highPerformance; // 是否需要高性能
boolean simpleImplementation; // 是否需要简单实现
boolean preventReflectionAttack; // 是否需要防止反射攻击
boolean preventSerializationAttack; // 是否需要防止序列化攻击
boolean distributedEnvironment; // 是否在分布式环境
// getters...
}
}
5.2 线程安全最佳实践
csharp
/**
* 线程安全的单例实现模板
*/
abstract class ThreadSafeSingleton<T> {
// 使用静态内部类实现延迟加载和线程安全
private static class SingletonHolder<T> {
private static volatile Object instance;
static <T> T getInstance(Supplier<T> creator) {
if (instance == null) {
synchronized (SingletonHolder.class) {
if (instance == null) {
instance = creator.get();
}
}
}
@SuppressWarnings("unchecked")
T result = (T) instance;
return result;
}
}
protected abstract T createInstance();
public final T getInstance() {
return SingletonHolder.getInstance(this::createInstance);
}
}
// 使用示例
class MySingleton extends ThreadSafeSingleton<MySingleton> {
private MySingleton() {
// 复杂的初始化
}
@Override
protected MySingleton createInstance() {
return new MySingleton();
}
}
5.3 防御性编程
csharp
/**
* 防御性单例 - 防止所有攻击
*/
class DefensiveSingleton implements Serializable, Cloneable {
private static final long serialVersionUID = 1L;
// 使用枚举Holder防止反射攻击
private enum SingletonHolder {
INSTANCE;
private final DefensiveSingleton instance;
SingletonHolder() {
instance = new DefensiveSingleton();
}
private DefensiveSingleton getInstance() {
return instance;
}
}
private DefensiveSingleton() {
// 防止反射攻击
if (SingletonHolder.INSTANCE.instance != null) {
throw new RuntimeException("禁止通过反射创建实例");
}
System.out.println("DefensiveSingleton 初始化");
}
public static DefensiveSingleton getInstance() {
return SingletonHolder.INSTANCE.getInstance();
}
// 防止序列化攻击
protected Object readResolve() {
return getInstance();
}
// 防止克隆攻击
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("单例对象不允许克隆");
}
// 防止反序列化攻击
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("禁止反序列化单例对象");
}
private void writeObject(ObjectOutputStream oos) throws IOException {
throw new InvalidObjectException("禁止序列化单例对象");
}
}
5.4 测试友好设计
typescript
/**
* 可测试的单例设计
*/
class TestableSingleton {
private static TestableSingleton instance;
private final Dependency dependency;
// 包私有构造器,便于测试
TestableSingleton(Dependency dependency) {
this.dependency = dependency;
}
// 生产环境使用
public static TestableSingleton getInstance() {
if (instance == null) {
synchronized (TestableSingleton.class) {
if (instance == null) {
instance = new TestableSingleton(new RealDependency());
}
}
}
return instance;
}
// 测试环境使用
static void setTestInstance(TestableSingleton testInstance) {
instance = testInstance;
}
// 重置实例(仅用于测试)
static void reset() {
instance = null;
}
public void doBusiness() {
dependency.doSomething();
}
// 依赖接口
interface Dependency {
void doSomething();
}
// 真实依赖
static class RealDependency implements Dependency {
@Override
public void doSomething() {
// 真实的业务逻辑
}
}
// Mock依赖
static class MockDependency implements Dependency {
@Override
public void doSomething() {
// Mock实现
}
}
}
// 测试用例
class TestableSingletonTest {
@Before
public void setUp() {
TestableSingleton.reset();
}
@Test
public void testBusiness() {
// 使用Mock依赖
TestableSingleton.setTestInstance(
new TestableSingleton(new MockDependency())
);
TestableSingleton instance = TestableSingleton.getInstance();
instance.doBusiness();
// 验证行为
}
}
5.5 Spring集成最佳实践
typescript
/**
* 在Spring中使用单例的最佳实践
*/
@Configuration
class SingletonSpringConfig {
/**
* 方法1:使用@Bean注解
* Spring默认单例,但可以控制初始化
*/
@Bean
@Lazy // 延迟初始化
public ExpensiveService expensiveService() {
return new ExpensiveService();
}
/**
* 方法2:结合@PostConstruct和@PreDestroy
* 管理单例生命周期
*/
@Bean
public LifecycleSingleton lifecycleSingleton() {
return new LifecycleSingleton();
}
/**
* 方法3:使用FactoryBean
* 复杂的单例创建逻辑
*/
@Bean
public ComplexSingletonFactory complexSingletonFactory() {
return new ComplexSingletonFactory();
}
}
/**
* 生命周期管理的单例
*/
class LifecycleSingleton {
@PostConstruct
public void init() {
// 初始化逻辑
System.out.println("LifecycleSingleton 初始化");
}
public void doSomething() {
// 业务逻辑
}
@PreDestroy
public void destroy() {
// 清理逻辑
System.out.println("LifecycleSingleton 销毁");
}
}
/**
* 工厂Bean创建单例
*/
class ComplexSingletonFactory implements FactoryBean<ComplexSingleton> {
private ComplexSingleton instance;
@Override
public ComplexSingleton getObject() throws Exception {
if (instance == null) {
synchronized (this) {
if (instance == null) {
instance = createComplexSingleton();
}
}
}
return instance;
}
@Override
public Class<?> getObjectType() {
return ComplexSingleton.class;
}
@Override
public boolean isSingleton() {
return true;
}
private ComplexSingleton createComplexSingleton() {
// 复杂的创建逻辑
return new ComplexSingleton();
}
}
/**
* 在非Spring环境中模拟Spring的单例管理
*/
class SingletonManager {
private static final Map<String, Object> singletons = new ConcurrentHashMap<>();
private static final Map<String, Runnable> destroyCallbacks = new ConcurrentHashMap<>();
/**
* 注册单例
*/
public static <T> void registerSingleton(String name, T instance) {
if (singletons.containsKey(name)) {
throw new IllegalStateException("单例已存在: " + name);
}
singletons.put(name, instance);
}
/**
* 注册带销毁回调的单例
*/
public static <T> void registerSingleton(String name, T instance, Runnable destroyCallback) {
registerSingleton(name, instance);
if (destroyCallback != null) {
destroyCallbacks.put(name, destroyCallback);
}
}
/**
* 获取单例
*/
@SuppressWarnings("unchecked")
public static <T> T getSingleton(String name) {
return (T) singletons.get(name);
}
/**
* 销毁所有单例
*/
public static void destroyAll() {
// 按注册的逆序销毁
List<String> names = new ArrayList<>(destroyCallbacks.keySet());
Collections.reverse(names);
for (String name : names) {
try {
destroyCallbacks.get(name).run();
} catch (Exception e) {
e.printStackTrace();
}
}
singletons.clear();
destroyCallbacks.clear();
}
}
六、实战案例:完整的单例应用
csharp
/**
* 实战案例:全局事件总线(单例实现)
* 应用场景:组件间通信,解耦业务模块
*/
class GlobalEventBus {
// 枚举实现单例
public enum Instance {
INSTANCE;
private final EventBus eventBus;
private final Map<Class<?>, List<EventHandler>> handlers = new ConcurrentHashMap<>();
private final ExecutorService executor = Executors.newFixedThreadPool(4);
Instance() {
this.eventBus = new EventBus("GlobalEventBus");
}
/**
* 注册事件处理器
*/
public <T> void register(Class<T> eventType, EventHandler<T> handler) {
handlers.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>())
.add(handler);
}
/**
* 取消注册
*/
public <T> void unregister(Class<T> eventType, EventHandler<T> handler) {
List<EventHandler> list = handlers.get(eventType);
if (list != null) {
list.remove(handler);
}
}
/**
* 发布事件(同步)
*/
public <T> void publish(T event) {
List<EventHandler> list = handlers.get(event.getClass());
if (list != null) {
for (EventHandler handler : list) {
try {
handler.handle(event);
} catch (Exception e) {
// 记录日志,但不影响其他处理器
System.err.println("事件处理失败: " + e.getMessage());
}
}
}
}
/**
* 发布事件(异步)
*/
public <T> void publishAsync(T event) {
executor.submit(() -> publish(event));
}
/**
* 关闭事件总线
*/
public void shutdown() {
executor.shutdown();
try {
if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
// 便捷访问方法
public static GlobalEventBus getInstance() {
return Instance.INSTANCE.eventBus;
}
public static <T> void registerHandler(Class<T> eventType, EventHandler<T> handler) {
Instance.INSTANCE.register(eventType, handler);
}
public static <T> void publishEvent(T event) {
Instance.INSTANCE.publish(event);
}
public static <T> void publishEventAsync(T event) {
Instance.INSTANCE.publishAsync(event);
}
public static void shutdown() {
Instance.INSTANCE.shutdown();
}
// 事件处理器接口
@FunctionalInterface
public interface EventHandler<T> {
void handle(T event);
}
// 事件总线
static class EventBus {
private final String name;
EventBus(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
// 使用示例
static class UserLoginEvent {
private final String username;
private final long timestamp;
public UserLoginEvent(String username) {
this.username = username;
this.timestamp = System.currentTimeMillis();
}
public String getUsername() { return username; }
public long getTimestamp() { return timestamp; }
}
static class OrderCreatedEvent {
private final String orderId;
private final double amount;
public OrderCreatedEvent(String orderId, double amount) {
this.orderId = orderId;
this.amount = amount;
}
public String getOrderId() { return orderId; }
public double getAmount() { return amount; }
}
public static void main(String[] args) {
// 注册事件处理器
GlobalEventBus.registerHandler(UserLoginEvent.class, event -> {
System.out.println("用户登录: " + event.getUsername());
// 记录登录日志
// 发送登录通知
// 更新用户状态
});
GlobalEventBus.registerHandler(OrderCreatedEvent.class, event -> {
System.out.println("订单创建: " + event.getOrderId() + ", 金额: " + event.getAmount());
// 发送订单通知
// 更新库存
// 计算佣金
});
GlobalEventBus.registerHandler(OrderCreatedEvent.class, event -> {
// 另一个处理器
System.out.println("发送短信通知: 订单 " + event.getOrderId() + " 已创建");
});
// 发布事件
GlobalEventBus.publishEvent(new UserLoginEvent("张三"));
GlobalEventBus.publishEventAsync(new OrderCreatedEvent("ORD202401010001", 299.99));
// 等待异步处理完成
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 关闭
GlobalEventBus.shutdown();
}
}
总结
单例模式是设计模式中最常用也最容易被误用的模式。正确使用单例模式可以:
- 提高系统性能:通过资源共享减少资源消耗
- 保证数据一致性:通过统一入口管理状态
- 简化系统设计:通过减少重复代码降低复杂度
但需要特别注意:
- 线程安全:多线程环境下必须保证安全
- 序列化安全:防止序列化攻击
- 反射安全:防止反射攻击
- 测试友好:设计可测试的单例
- 合理使用:避免滥用单例导致系统僵化
在Spring等现代框架中,通常推荐使用IoC容器管理单例,而不是手动实现。但在框架底层、工具类、资源管理等场景,正确实现的单例模式仍然具有重要价值。