您好,登录后才能下订单哦!
# 怎么实现Java单例模式
## 一、单例模式概述
单例模式(Singleton Pattern)是Java中最简单的设计模式之一,属于创建型模式。它保证一个类仅有一个实例,并提供一个全局访问点。
### 1.1 核心特性
- **唯一实例**:确保类只有一个实例存在
- **全局访问**:提供统一的访问入口
- **自我管理**:类自身控制实例化过程
### 1.2 应用场景
- 需要频繁创建销毁的对象
- 重量级对象(如数据库连接池)
- 工具类对象
- 需要共享访问的配置对象
## 二、基础实现方式
### 2.1 饿汉式(Eager Initialization)
```java
public class EagerSingleton {
// 类加载时就初始化
private static final EagerSingleton instance = new EagerSingleton();
// 私有构造器
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return instance;
}
}
优点: - 实现简单 - 线程安全(由JVM类加载机制保证)
缺点: - 可能造成资源浪费(未使用时也加载) - 无法传递参数初始化
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
优点: - 延迟加载 - 节省资源
缺点: - 线程不安全(多线程可能创建多个实例)
public class SyncSingleton {
private static SyncSingleton instance;
private SyncSingleton() {}
public static synchronized SyncSingleton getInstance() {
if (instance == null) {
instance = new SyncSingleton();
}
return instance;
}
}
问题:每次获取实例都要同步,性能差
public class DCLSingleton {
private volatile static DCLSingleton instance;
private DCLSingleton() {}
public static DCLSingleton getInstance() {
if (instance == null) { // 第一次检查
synchronized (DCLSingleton.class) {
if (instance == null) { // 第二次检查
instance = new DCLSingleton();
}
}
}
return instance;
}
}
关键点:
- volatile
防止指令重排序
- 减少同步块范围
- 两次null检查确保唯一性
public class HolderSingleton {
private HolderSingleton() {}
private static class SingletonHolder {
private static final HolderSingleton INSTANCE = new HolderSingleton();
}
public static HolderSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
原理: - 利用类加载机制保证线程安全 - 只有调用getInstance()时才会加载Holder类
public enum EnumSingleton {
INSTANCE;
public void doSomething() {
// 业务方法
}
}
优势: - 绝对防止多实例 - 自动支持序列化 - 防止反射攻击
public class ThreadLocalSingleton {
private static final ThreadLocal<ThreadLocalSingleton> instance =
ThreadLocal.withInitial(ThreadLocalSingleton::new);
private ThreadLocalSingleton() {}
public static ThreadLocalSingleton getInstance() {
return instance.get();
}
}
特点:线程内单例,不同线程不同实例
反射攻击
Constructor<DCLSingleton> constructor = DCLSingleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
DCLSingleton newInstance = constructor.newInstance();
序列化/反序列化 “`java // 序列化 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“singleton”)); oos.writeObject(DCLSingleton.getInstance());
// 反序列化 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(“singleton”)); DCLSingleton newInstance = (DCLSingleton) ois.readObject();
### 5.2 防护措施
1. 防止反射:
```java
private DCLSingleton() {
if (instance != null) {
throw new RuntimeException("禁止反射创建实例");
}
}
protected Object readResolve() {
return getInstance();
}
实现方式 | 线程安全 | 延迟加载 | 性能 | 防反射 | 防序列化 |
---|---|---|---|---|---|
饿汉式 | ✓ | ✗ | ⭐⭐⭐⭐ | ✗ | ✗ |
懒汉式 | ✗ | ✓ | ⭐⭐ | ✗ | ✗ |
同步方法 | ✓ | ✓ | ⭐ | ✗ | ✗ |
双重检查锁 | ✓ | ✓ | ⭐⭐⭐ | ✗ | ✗ |
静态内部类 | ✓ | ✓ | ⭐⭐⭐⭐ | ✗ | ✗ |
枚举 | ✓ | ✗ | ⭐⭐⭐⭐ | ✓ | ✓ |
import java.io.*;
/**
* 强化版双重检查锁单例
*/
public class EnhancedSingleton implements Serializable {
private static volatile EnhancedSingleton instance;
private EnhancedSingleton() {
// 防止反射攻击
if (instance != null) {
throw new RuntimeException("禁止通过反射创建实例");
}
}
public static EnhancedSingleton getInstance() {
if (instance == null) {
synchronized (EnhancedSingleton.class) {
if (instance == null) {
instance = new EnhancedSingleton();
}
}
}
return instance;
}
// 防止序列化破坏
protected Object readResolve() {
return getInstance();
}
public void showMessage() {
System.out.println("Hello Singleton!");
}
}
/**
* 测试类
*/
class SingletonTest {
public static void main(String[] args) {
EnhancedSingleton singleton = EnhancedSingleton.getInstance();
singleton.showMessage();
// 测试获取的是否是同一实例
EnhancedSingleton anotherSingleton = EnhancedSingleton.getInstance();
System.out.println("是否为同一实例: " + (singleton == anotherSingleton));
}
}
单例模式看似简单,实则包含许多设计细节。在实际开发中,需要根据具体场景选择合适的实现方式:
正确使用单例模式可以显著提高系统性能,但滥用也可能导致内存泄漏、测试困难等问题。建议在明确需要全局唯一实例的场景下谨慎使用。 “`
注:本文实际约3600字,完整展开各代码示例的解析和性能测试部分可达到3700字要求。如需进一步扩展,可以: 1. 增加各模式的UML类图 2. 添加JMH性能测试数据 3. 补充更多实际应用案例 4. 深入分析JVM层面的实现原理
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。