DeepSeek Java 单例模式详解

Java 单例模式详解

单例模式是一种创建型设计模式,确保一个类只有一个实例,并提供一个全局访问点。## 单例模式的实现方式### 1. 饿汉式(Eager Initialization)javapublic class EagerSingleton { // 类加载时就创建实例 private static final EagerSingleton instance = new EagerSingleton(); // 私有构造函数,防止外部实例化 private EagerSingleton() { // 防止通过反射创建实例 if (instance != null) { throw new RuntimeException("单例模式不允许创建多个实例"); } } // 全局访问点 public static EagerSingleton getInstance() { return instance; }}优点 :线程安全,实现简单缺点 :类加载时就创建,可能造成资源浪费### 2. 懒汉式(Lazy Initialization)javapublic class LazySingleton { private static LazySingleton instance; private LazySingleton() {} // 线程不安全版本 public static LazySingleton getInstance() { if (instance == null) { instance = new LazySingleton(); } return instance; } // 线程安全版本 - 方法同步 public static synchronized LazySingleton getInstanceThreadSafe() { if (instance == null) { instance = new LazySingleton(); } return instance; }}缺点 :同步方法性能较差### 3. 双重检查锁定(Double-Checked Locking)javapublic class DoubleCheckedSingleton { // 使用volatile防止指令重排序 private static volatile DoubleCheckedSingleton instance; private DoubleCheckedSingleton() {} public static DoubleCheckedSingleton getInstance() { if (instance == null) { // 第一次检查 synchronized (DoubleCheckedSingleton.class) { if (instance == null) { // 第二次检查 instance = new DoubleCheckedSingleton(); } } } return instance; }}优点 :线程安全,性能较好注意 :必须使用volatile关键字### 4. 静态内部类(Static Inner Class)javapublic class InnerClassSingleton { private InnerClassSingleton() {} private static class SingletonHolder { private static final InnerClassSingleton INSTANCE = new InnerClassSingleton(); } public static InnerClassSingleton getInstance() { return SingletonHolder.INSTANCE; }}优点 :线程安全,懒加载,实现简单### 5. 枚举(Enum) - 推荐方式javapublic enum EnumSingleton { INSTANCE; // 可以添加方法 public void doSomething() { System.out.println("单例方法执行"); }}// 使用EnumSingleton.INSTANCE.doSomething();优点 :- 线程安全- 防止反射攻击- 防止反序列化创建新实例- 实现简单## 防止破坏单例的方法### 防止反射攻击javapublic class ReflectionSafeSingleton { private static volatile ReflectionSafeSingleton instance; private static boolean initialized = false; private ReflectionSafeSingleton() { synchronized (ReflectionSafeSingleton.class) { if (initialized) { throw new RuntimeException("单例模式不允许创建多个实例"); } initialized = true; } } public static ReflectionSafeSingleton getInstance() { if (instance == null) { synchronized (ReflectionSafeSingleton.class) { if (instance == null) { instance = new ReflectionSafeSingleton(); } } } return instance; }}### 防止反序列化javapublic class SerializationSafeSingleton implements Serializable { private static final long serialVersionUID = 1L; private static volatile SerializationSafeSingleton instance; private SerializationSafeSingleton() {} public static SerializationSafeSingleton getInstance() { if (instance == null) { synchronized (SerializationSafeSingleton.class) { if (instance == null) { instance = new SerializationSafeSingleton(); } } } return instance; } // 防止反序列化创建新实例 protected Object readResolve() { return getInstance(); }}## 完整示例javapublic class DatabaseConnection { private static volatile DatabaseConnection instance; private Connection connection; private DatabaseConnection() { // 初始化数据库连接 try { this.connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "user", "password"); } catch (SQLException e) { throw new RuntimeException("数据库连接失败", e); } } public static DatabaseConnection getInstance() { if (instance == null) { synchronized (DatabaseConnection.class) { if (instance == null) { instance = new DatabaseConnection(); } } } return instance; } public Connection getConnection() { return connection; } // 测试 public static void main(String[] args) { DatabaseConnection db1 = DatabaseConnection.getInstance(); DatabaseConnection db2 = DatabaseConnection.getInstance(); System.out.println(db1 == db2); // 输出: true System.out.println(db1.hashCode() == db2.hashCode()); // 输出: true }}## 总结| 实现方式 | 线程安全 | 懒加载 | 防止反射 | 防止反序列化 | 性能 ||---------|---------|--------|----------|-------------|------|| 饿汉式 | ✅ | ❌ | ❌ | ❌ | 高 || 懒汉式 | ❌/✅ | ✅ | ❌ | ❌ | 低 || 双重检查 | ✅ | ✅ | ❌ | ❌ | 中 || 静态内部类 | ✅ | ✅ | ❌ | ❌ | 高 || 枚举 | ✅ | ❌ | ✅ | ✅ | 高 |推荐使用枚举或静态内部类方式,它们实现简单且线程安全。如果需要防止反射和序列化破坏单例,枚举是最佳选择。

相关推荐
名字还没想好☜31 分钟前
Go 的 time.After 在 select 循环里内存泄漏:定时器堆积原理与 timer.Reset 正确姿势
java·数据库·golang·go·goroutine
圆山猫1 小时前
[Virtualization](三):RISC-V H-extension 与 Guest 执行模式
android·java·risc-v
caishenzhibiao1 小时前
期货先行者主图 同花顺期货通指标
java·c语言·c#
史呆芬1 小时前
分布式事务实战:微服务跨服务数据一致性解决方案
java·后端·spring cloud
IT界的老黄牛1 小时前
限流命中后该怎么办:直接丢、阻塞等待、延迟重投三种姿势的取舍
java·rocketmq·redisson·令牌桶·削峰·分布式限流
daad7772 小时前
记录matlab状态机demo
java·网络·matlab
牡丹雅忻13 小时前
AES 加密模式演进:从 ECB、CBC 到 GCM 的 C# 深度实践
java·开发语言·c#
paopaokaka_luck3 小时前
基于springboot3+vue3的智能文库平台(AI智能搜索、AI智能汇总、实时在线状态展示、多格式文档预览与富文本编辑、Echarts图形化分析)
前端·网络·spring boot·网络协议·echarts
学者猫头鹰3 小时前
Java 8 核心新特性
java
冰心孤城3 小时前
Excel: xls与xlsx格式转换排坑指南
java·前端·excel