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 }}## 总结| 实现方式 | 线程安全 | 懒加载 | 防止反射 | 防止反序列化 | 性能 ||---------|---------|--------|----------|-------------|------|| 饿汉式 | ✅ | ❌ | ❌ | ❌ | 高 || 懒汉式 | ❌/✅ | ✅ | ❌ | ❌ | 低 || 双重检查 | ✅ | ✅ | ❌ | ❌ | 中 || 静态内部类 | ✅ | ✅ | ❌ | ❌ | 高 || 枚举 | ✅ | ❌ | ✅ | ✅ | 高 |推荐使用枚举或静态内部类方式,它们实现简单且线程安全。如果需要防止反射和序列化破坏单例,枚举是最佳选择。

相关推荐
Freak嵌入式4 分钟前
Pico UART 数据收发实战:硬件配置、MicroPython 编程
java·开发语言·单片机·嵌入式硬件·生活
devilnumber1 小时前
Oracle 与 MySQL substr 函数差异总结
java·数据库·mysql·oracle
cfm_29141 小时前
线程池阻塞队列
java·开发语言
学代码的CJY1 小时前
Linux 重定向、管道与环境变量
linux·spring boot·spring
坐吃山猪1 小时前
【多线程】ThreadPool线程池参数说明
java·网络
evans在进步2 小时前
Java 常用设计模式(二):装饰器、适配器、责任链、模板方法、策略与观察者
java·开发语言·设计模式
jvmind_dev2 小时前
频繁 new JedisCluster 之后,对象池为什么回不去了?
java·后端
AKA__Zas2 小时前
文件 I/O(速通版
java·intellij-idea·学习方法
学长毕业设计2 小时前
基于SpringBoot的咖啡馆管理系统的设计与实现(源码+文档+讲解视频)
java·spring boot·后端
骇客野人2 小时前
SpringBoot业财一体化系统设计和落地实施方案
java·spring boot·后端