Java懒汉单例案例如何实操

wen java案例 25

本文目录导读:

Java懒汉单例案例如何实操

  1. 基础懒汉单例(线程不安全)
  2. 线程安全懒汉单例(synchronized方法)
  3. 双重检查锁定(推荐方式)
  4. 静态内部类方式(推荐方式)
  5. 完整实操案例
  6. 推荐使用场景
  7. 完整测试类

我来详细讲解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
    }
}
  1. 双重检查锁定:使用 volatile 防止指令重排序
  2. 静态内部类:利用类加载机制保证线程安全
  3. 防止反射:在构造方法中添加检查
  4. 懒加载:只有在调用 getInstance() 时才创建实例

推荐使用静态内部类方式实现懒汉单例,既保证了线程安全,又实现了懒加载,代码简洁高效。

抱歉,评论功能暂时关闭!