单例模式多种写法案例

wen java案例 2

本文目录导读:

单例模式多种写法案例

  1. 饿汉式(静态常量)
  2. 饿汉式(静态代码块)
  3. 懒汉式(线程不安全)
  4. 懒汉式(同步方法)
  5. 双重检查锁(DCL)
  6. 静态内部类(推荐)
  7. 枚举方式(最佳实践)
  8. 完整对比代码(含测试)
  9. 选型建议
  10. 完整演示代码(可直接运行)

我为您整理了单例模式的多种经典写法,每种都有其适用场景和优缺点。

饿汉式(静态常量)

public class SingletonEager {
    // 类加载时就创建实例
    private static final SingletonEager INSTANCE = new SingletonEager();
    private SingletonEager() {}
    public static SingletonEager getInstance() {
        return INSTANCE;
    }
}

优点:简单,线程安全
缺点:类加载时就创建实例,可能造成资源浪费


饿汉式(静态代码块)

public class SingletonStaticBlock {
    private static SingletonStaticBlock instance;
    static {
        instance = new SingletonStaticBlock();
    }
    private SingletonStaticBlock() {}
    public static SingletonStaticBlock getInstance() {
        return instance;
    }
}

适用场景:可以在静态代码块中添加更多初始化逻辑


懒汉式(线程不安全)

public class SingletonLazy {
    private static SingletonLazy instance;
    private SingletonLazy() {}
    public static SingletonLazy getInstance() {
        if (instance == null) {  // 单线程环境可用
            instance = new SingletonLazy();
        }
        return instance;
    }
}

缺点:多线程环境下不安全,不推荐使用


懒汉式(同步方法)

public class SingletonLazySync {
    private static SingletonLazySync instance;
    private SingletonLazySync() {}
    public static synchronized SingletonLazySync getInstance() {
        if (instance == null) {
            instance = new SingletonLazySync();
        }
        return instance;
    }
}

优点:线程安全
缺点:每次调用都需要同步,性能较低


双重检查锁(DCL)

public class SingletonDCL {
    // volatile 防止指令重排序
    private static volatile SingletonDCL instance;
    private SingletonDCL() {}
    public static SingletonDCL getInstance() {
        if (instance == null) {  // 第一次检查
            synchronized (SingletonDCL.class) {
                if (instance == null) {  // 第二次检查
                    instance = new SingletonDCL();
                }
            }
        }
        return instance;
    }
}

优点:线程安全,性能较好
注意:必须使用volatile关键字


静态内部类(推荐)

public class SingletonHolder {
    private SingletonHolder() {}
    // 静态内部类,调用getInstance时才会加载
    private static class SingletonInstance {
        private static final SingletonHolder INSTANCE = new SingletonHolder();
    }
    public static SingletonHolder getInstance() {
        return SingletonInstance.INSTANCE;
    }
}

优点

  • 线程安全(类加载机制保证)
  • 懒加载(使用时才加载内部类)
  • 性能好

枚举方式(最佳实践)

public enum SingletonEnum {
    INSTANCE;  // 枚举元素本身就是单例
    private String name = "singleton";
    public void showMessage() {
        System.out.println("枚举单例: " + name);
    }
    // 使用方式
    public static void main(String[] args) {
        SingletonEnum.INSTANCE.showMessage();
    }
}

优点

  • 最简单
  • 线程安全
  • 防反射攻击
  • 防序列化破坏

完整对比代码(含测试)

public class SingletonDemo {
    public static void main(String[] args) {
        // 测试各种单例
        testSingleton("饿汉式", SingletonEager::getInstance);
        testSingleton("静态代码块", SingletonStaticBlock::getInstance);
        testSingleton("懒汉式", SingletonLazySync::getInstance);
        testSingleton("双重检查锁", SingletonDCL::getInstance);
        testSingleton("静态内部类", SingletonHolder::getInstance);
        testSingleton("枚举", () -> SingletonEnum.INSTANCE);
        // 多线程测试
        testThreadSafety();
    }
    private static void testSingleton(String name, Supplier<Object> supplier) {
        Object s1 = supplier.get();
        Object s2 = supplier.get();
        System.out.println(name + " 是否为单例: " + (s1 == s2));
    }
    private static void testThreadSafety() {
        // 测试DCL是否线程安全
        ExecutorService pool = Executors.newFixedThreadPool(10);
        Set<SingletonDCL> set = ConcurrentHashMap.newKeySet();
        for (int i = 0; i < 100; i++) {
            pool.execute(() -> set.add(SingletonDCL.getInstance()));
        }
        pool.shutdown();
        System.out.println("DCL线程安全测试 实例数量: " + set.size());
    }
}

选型建议

  1. 最优选:枚举方式(SingletonEnum

    最简洁,天然线程安全,防止反射和序列化破坏

  2. 项目中常用:静态内部类(SingletonHolder

    实现简单,性能好,懒加载

  3. 注重性能:双重检查锁(SingletonDCL

    性能好,但注意volatile使用

  4. 简单场景:饿汉式(SingletonEager

    类不复杂,无资源浪费时使用

  5. 避免使用:纯懒汉式(非线程安全)


完整演示代码(可直接运行)

import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
// 在这里加入上面所有的单例类...
// 然后运行 SingletonDemo 测试

这8种写法覆盖了Java单例模式的所有经典实现,您可以根据实际项目需求选择最合适的方式,在实际开发中,枚举静态内部类是最高效、最安全的推荐方案。

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