单例模式

导读

单例模式(Singleton Pattern)是一种创建型设计模式 ,它确保一个类在整个应用程序生命周期中只有一个实例存在,并提供一个全局访问点来获取该实例。

在 Java 中,常见的实现方式主要有两种:饿汉式(Eager Initialization)懒汉式(Lazy Initialization)。它们各有优缺点,适用于不同场景。

实现方式 是否延迟加载 是否线程安全 是否推荐
饿汉式 ❌ 否 ✅ 是 ✅ 推荐(简单场景)
懒汉式(无锁) ✅ 是 ❌ 否 ❌ 不推荐
懒汉式(synchronized) ✅ 是 ✅ 是 ⚠️ 可接受(性能略差)
双重检查锁定 ✅ 是 ✅ 是 ✅ 推荐
静态内部类 ✅ 是 ✅ 是 ✅ 推荐
枚举 ✅ 是 ✅ 是 ✅✅ 最推荐

🎯 应用场景

  • 数据库连接池管理
  • 日志记录器(如 Logger
  • 配置管理类(如 Properties
  • Spring 中的 Bean 默认就是单例模式

一、饿汉式(Eager Initialization)

特点 :类加载时立即创建实例(急切初始化)
优点 :线程安全,无需加锁(由 JVM 类加载机制保证)
缺点:可能造成资源浪费(未使用时也占用内存)

1. 基础实现(静态变量)

java 复制代码
public class EagerSingleton {
    // 类加载时初始化实例
    private static final EagerSingleton INSTANCE = new EagerSingleton();
    
    private EagerSingleton() {}  // 私有构造器
    
    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

2. 静态代码块变体

java 复制代码
public class EagerSingleton {
    private static final EagerSingleton INSTANCE;
    
    static {
        try {
            INSTANCE = new EagerSingleton();
        } catch (Exception e) {
            throw new RuntimeException("初始化失败", e);
        }
    }
    
    public static EagerSingleton getInstance() {
        return INSTANCE;
    }
}

3. 枚举实现(终极方案)

java 复制代码
public enum EnumSingleton {
    INSTANCE;  // 单例实例
    
    public void doSomething() {
        // 业务方法
    }
}
// 使用:EnumSingleton.INSTANCE.doSomething();

优势

  • 绝对防止反射攻击
  • 自动处理序列化/反序列化
  • 线程安全
  • 代码最简洁(Java 官方推荐方式)

二、懒汉式(Lazy Initialization)

特点 :首次使用时创建实例(延迟初始化)
优点 :节省资源
缺点:需额外处理线程安全问题

1. 非线程安全基础版

java 复制代码
public class UnsafeLazySingleton {
    private static UnsafeLazySingleton instance;
    
    private UnsafeLazySingleton() {}
    
    public static UnsafeLazySingleton getInstance() {
        if (instance == null) {  // 线程不安全点
            instance = new UnsafeLazySingleton();
        }
        return instance;
    }
}

2. 线程安全同步方法版(低效)

java 复制代码
public class SynchronizedLazySingleton {
    private static SynchronizedLazySingleton instance;
    
    private SynchronizedLazySingleton() {}
    
    public static synchronized SynchronizedLazySingleton getInstance() {
        if (instance == null) {
            instance = new SynchronizedLazySingleton();
        }
        return instance;
    }
}

缺点:每次获取实例都同步,性能差

3. 双重检查锁定(DCL)版(高效线程安全)

java 复制代码
public class DoubleCheckedLockingSingleton {
    // volatile 禁止指令重排序
    private static volatile DoubleCheckedLockingSingleton instance;
    
    private DoubleCheckedLockingSingleton() {}
    
    public static DoubleCheckedLockingSingleton getInstance() {
        if (instance == null) {  // 第一次检查(无锁)
            synchronized (DoubleCheckedLockingSingleton.class) {
                if (instance == null) {  // 第二次检查(有锁)
                    instance = new DoubleCheckedLockingSingleton();
                }
            }
        }
        return instance;
    }
}

关键点

  • volatile 防止 JVM 指令重排序(避免返回未初始化的对象)
  • 两次判空确保单例

4. 静态内部类(Holder)模式(推荐)

java 复制代码
public class HolderSingleton {
    private HolderSingleton() {}
    
    private static class Holder {
        // 由 JVM 保证线程安全初始化
        static final HolderSingleton INSTANCE = new HolderSingleton();
    }
    
    public static HolderSingleton getInstance() {
        return Holder.INSTANCE;  // 首次调用时加载 Holder 类
    }
}

优势

  • 线程安全(JVM 类加载机制)
  • 懒加载(调用 getInstance() 时才初始化)
  • 无同步开销

五、选型建议

  1. 首选枚举方案(Java 5+)

    • 满足所有安全需求
    • 代码简洁明了(《Effective Java》推荐)
  2. 需要懒加载时

    • 静态内部类(平衡安全性与性能)
    • 避免使用基础同步方法(性能差)
  3. 明确需要饿加载

    • 简单场景用饿汉式
    • 需异常处理时用静态块变体
  4. 超高性能场景

    • 首选枚举饿汉式
    • 次选双重检查锁定(注意 volatile)

📌 设计原则:在满足需求的前提下,选择最简单的实现。单例模式已被认为是一种"反模式",过度使用会导致代码耦合度高、难以测试,建议结合依赖注入框架(如Spring)管理单例。

相关推荐
陈随易2 小时前
在 VSCode 里,把项目一键部署到服务器
前端·后端·程序员
鱼樱前端2 小时前
我用 Claude Code 后,编码效率翻 3 倍。但更值钱的是别的。
前端·后端·ai编程
犀利豆3 小时前
Claude code tools 研究系列-开篇(AskUserQuestion)
后端
颜酱6 小时前
06 | 把 meta_config 同步进 MySQL(生成阶段)
前端·人工智能·后端
IT_陈寒6 小时前
SpringBoot自动配置坑了我一周,原来问题这么蠢!
前端·人工智能·后端
iOS开发上架哦7 小时前
Android代码混淆与iOS加固技术详解
后端·ios
Alan_6918 小时前
商品详情优化三板斧-拆分-多级缓存-GC调参
后端·缓存
Conan在掘金8 小时前
ArkTS 进阶之道(3):为哈禁解构声明?类型一眼可见 vs 推断链断裂
后端
晚安code8 小时前
干掉成山的 if-else:工厂造、策略选,一文讲透两个模式的配合
后端·设计模式
feng尘8 小时前
深度解析布隆过滤器(Bloom Filter):原理、优缺点与 1000 万黑名单实战
后端·面试