本文目录导读:

- 饿汉式(线程安全)
- 懒汉式(线程不安全)
- 懒汉式(同步方法,性能较低)
- Double-Checked Locking(双重检查锁定)
- 静态内部类(推荐方式)
- 枚举方式(最安全的实现方式)
- 完整测试代码
- 防止反射和序列化攻击
- 总结与选择建议
我来详细介绍Java单例模式的几种经典实现方式。
饿汉式(线程安全)
/**
* 饿汉式:类加载时就创建实例,线程安全
*/
public class Singleton {
// 私有静态实例,类加载时创建
private static final Singleton INSTANCE = new Singleton();
// 私有构造方法
private Singleton() {
System.out.println("Singleton 实例已创建");
}
// 公共的获取实例方法
public static Singleton getInstance() {
return INSTANCE;
}
// 业务方法示例
public void doSomething() {
System.out.println("执行业务逻辑");
}
}
懒汉式(线程不安全)
/**
* 懒汉式:第一次调用时创建实例,线程不安全
*/
public class Singleton {
private static Singleton instance;
private Singleton() {
System.out.println("Singleton 实例已创建");
}
public static Singleton getInstance() {
if (instance == null) { // 线程不安全
instance = new Singleton();
}
return instance;
}
}
懒汉式(同步方法,性能较低)
/**
* 懒汉式:使用synchronized同步方法,线程安全但性能低
*/
public class Singleton {
private static Singleton instance;
private Singleton() {}
// 同步整个方法,每次获取实例都需要获取锁
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
Double-Checked Locking(双重检查锁定)
/**
* 双重检查锁定:推荐使用,线程安全且性能较好
*/
public class Singleton {
// volatile关键字保证可见性和禁止指令重排序
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;
}
}
静态内部类(推荐方式)
/**
* 静态内部类:线程安全,延迟加载,推荐使用
*/
public class Singleton {
// 私有构造方法
private Singleton() {}
// 静态内部类,只有在第一次使用时才会加载
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
// 获取实例方法
public static Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
// 业务方法
public void doSomething() {
System.out.println("使用单例对象执行业务");
}
}
枚举方式(最安全的实现方式)
/**
* 枚举单例:天然线程安全,防止反射攻击和序列化问题
*/
public enum Singleton {
INSTANCE; // 唯一的实例
// 可以添加其他字段和方法
private String config;
// 枚举构造函数
Singleton() {
this.config = "默认配置";
System.out.println("枚举单例初始化");
}
// 业务方法
public void doSomething() {
System.out.println("使用枚举单例:" + config);
}
// getter/setter
public String getConfig() {
return config;
}
public void setConfig(String config) {
this.config = config;
}
}
完整测试代码
public class SingletonTest {
public static void main(String[] args) {
// 测试饿汉式
System.out.println("=== 饿汉式测试 ===");
Singleton.instance.doSomething();
// 测试静态内部类
System.out.println("\n=== 静态内部类测试 ===");
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println("是否是同一个实例:" + (instance1 == instance2));
// 测试枚举单例
System.out.println("\n=== 枚举单例测试 ===");
SingletonEnum.INSTANCE.doSomething();
SingletonEnum.INSTANCE.setConfig("自定义配置");
SingletonEnum.INSTANCE.doSomething();
// 多线程测试
System.out.println("\n=== 多线程测试 ===");
for (int i = 0; i < 10; i++) {
new Thread(() -> {
Singleton singleton = Singleton.getInstance();
System.out.println(Thread.currentThread().getName() + ": " + singleton);
}).start();
}
}
}
防止反射和序列化攻击
import java.io.Serializable;
/**
* 安全的单例:防止反射和序列化破坏
*/
public class SafeSingleton implements Serializable {
private static final long serialVersionUID = 1L;
private static volatile SafeSingleton instance;
private SafeSingleton() {
// 防止反射创建实例
if (instance != null) {
throw new RuntimeException("不允许创建多个实例!");
}
}
public static SafeSingleton getInstance() {
if (instance == null) {
synchronized (SafeSingleton.class) {
if (instance == null) {
instance = new SafeSingleton();
}
}
}
return instance;
}
// 防止序列化破坏单例
private Object readResolve() {
return getInstance();
}
}
总结与选择建议
| 实现方式 | 线程安全 | 延迟加载 | 推荐度 | 适用场景 |
|---|---|---|---|---|
| 饿汉式 | 简单场景,实例不复杂 | |||
| 懒汉式(同步) | 不推荐,性能差 | |||
| 双重检查锁定 | 高性能需求 | |||
| 静态内部类 | 推荐,简洁高效 | |||
| 枚举 | 最推荐,安全可靠 |
推荐使用:
- 一般场景:静态内部类 或 双重检查锁定
- 需要最佳安全性:枚举方式
- 简单场景:饿汉式