本文目录导读:

我来详细讲解Java懒汉单例模式的几种实操方式,从简单到优化的演进过程。
基础懒汉单例(线程不安全)
public class LazySingleton {
// 私有静态变量
private static LazySingleton instance;
// 私有构造方法
private LazySingleton() {
System.out.println("懒汉单例被创建");
}
// 公开获取实例方法
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
public void showMessage() {
System.out.println("Hello from Lazy Singleton!");
}
}
线程安全懒汉单例(synchronized方法)
public class ThreadSafeLazySingleton {
private static ThreadSafeLazySingleton instance;
private ThreadSafeLazySingleton() {}
// 使用synchronized保证线程安全
public static synchronized ThreadSafeLazySingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeLazySingleton();
}
return instance;
}
}
双重检查锁定(推荐方式)
public class DoubleCheckedSingleton {
// volatile关键字禁止指令重排序
private static volatile DoubleCheckedSingleton instance;
private DoubleCheckedSingleton() {
// 防止反射攻击
if (instance != null) {
throw new RuntimeException("禁止反射创建实例");
}
System.out.println("DoubleCheckedSingleton 创建");
}
public static DoubleCheckedSingleton getInstance() {
// 第一次检查
if (instance == null) {
// 类级别锁
synchronized (DoubleCheckedSingleton.class) {
// 第二次检查
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}
静态内部类方式(推荐方式)
public class StaticInnerClassSingleton {
private StaticInnerClassSingleton() {
System.out.println("StaticInnerClassSingleton 创建");
}
// 静态内部类
private static class SingletonHolder {
private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
完整实操案例
public class LazySingletonDemo {
public static void main(String[] args) {
System.out.println("=== 懒汉单例测试 ===\n");
// 1. 单线程测试
System.out.println("=== 单线程测试 ===");
LazySingleton singleton1 = LazySingleton.getInstance();
LazySingleton singleton2 = LazySingleton.getInstance();
System.out.println("singleton1 == singleton2: " + (singleton1 == singleton2));
System.out.println();
// 2. 多线程测试双重检查锁定
System.out.println("=== 多线程测试 ===");
Runnable task = () -> {
DoubleCheckedSingleton instance = DoubleCheckedSingleton.getInstance();
System.out.println(Thread.currentThread().getName() + " 获取实例: " + instance.hashCode());
};
// 创建多个线程并发获取实例
Thread[] threads = new Thread[5];
for (int i = 0; i < threads.length; i++) {
threads[i] = new Thread(task, "线程-" + (i + 1));
threads[i].start();
}
// 等待所有线程完成
for (Thread thread : threads) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 3. 展示静态内部类方式
System.out.println("\n=== 静态内部类测试 ===");
StaticInnerClassSingleton inner1 = StaticInnerClassSingleton.getInstance();
StaticInnerClassSingleton inner2 = StaticInnerClassSingleton.getInstance();
System.out.println("inner1 == inner2: " + (inner1 == inner2));
}
}
// 测试结果示例:
// === 懒汉单例测试 ===
//
// === 单线程测试 ===
// 懒汉单例被创建
// singleton1 == singleton2: true
//
// === 多线程测试 ===
// DoubleCheckedSingleton 创建
// 线程-1 获取实例: 123456789
// 线程-2 获取实例: 123456789
// 线程-3 获取实例: 123456789
// 线程-4 获取实例: 123456789
// 线程-5 获取实例: 123456789
//
// === 静态内部类测试 ===
// StaticInnerClassSingleton 创建
// inner1 == inner2: true
推荐使用场景
生产环境推荐方案
// 方案1:双重检查锁定(需要JDK5+)
public class SingletonA {
private static volatile SingletonA instance;
private SingletonA() {
if (instance != null) {
throw new RuntimeException("禁止反射");
}
}
public static SingletonA getInstance() {
if (instance == null) {
synchronized (SingletonA.class) {
if (instance == null) {
instance = new SingletonA();
}
}
}
return instance;
}
}
// 方案2:静态内部类(最简洁安全)
public class SingletonB {
private SingletonB() {}
private static class Holder {
static final SingletonB INSTANCE = new SingletonB();
}
public static SingletonB getInstance() {
return Holder.INSTANCE;
}
}
完整测试类
public class CompleteTest {
public static void main(String[] args) throws Exception {
// 验证单例
System.out.println("测试单例模式:");
// 验证双重检查锁定
DoubleCheckedSingleton d1 = DoubleCheckedSingleton.getInstance();
DoubleCheckedSingleton d2 = DoubleCheckedSingleton.getInstance();
System.out.println("双重检查锁定: " + (d1 == d2)); // true
// 验证静态内部类
StaticInnerClassSingleton s1 = StaticInnerClassSingleton.getInstance();
StaticInnerClassSingleton s2 = StaticInnerClassSingleton.getInstance();
System.out.println("静态内部类: " + (s1 == s2)); // true
}
}
- 双重检查锁定:使用
volatile防止指令重排序 - 静态内部类:利用类加载机制保证线程安全
- 防止反射:在构造方法中添加检查
- 懒加载:只有在调用
getInstance()时才创建实例
推荐使用静态内部类方式实现懒汉单例,既保证了线程安全,又实现了懒加载,代码简洁高效。