第 1 天:单例模式(Singleton Pattern)—— 创建型模式

第 1 天:单例模式(Singleton Pattern)------ 创建型模式

1. 核心定义

单例模式确保一个类仅有一个实例 ,并提供一个全局访问点来获取该实例。它的核心是 "控制实例数量",避免重复创建消耗资源的对象(如数据库连接池、配置管理器)。

2. 解决的核心问题

  • 避免多个实例导致的资源浪费(如频繁创建数据库连接);
  • 防止多个实例引发的数据不一致(如配置文件读取实例,多实例可能导致配置冲突);
  • 提供统一的全局访问入口,简化对象调用。

3. 关键设计要点

  • 私有构造函数 :禁止外部通过 new 关键字创建实例;
  • 私有静态成员变量:存储类的唯一实例;
  • 公有静态方法:作为全局访问点,返回唯一实例(需处理线程安全问题)。

4. 常见实现方式(Java 示例)

方式 1:饿汉式(线程安全,简单但可能浪费资源)

"饿汉式" 在类加载时就创建实例,避免线程安全问题,但如果实例未被使用,会提前占用内存。

csharp 复制代码
public class HungrySingleton {
    // 1. 私有静态成员变量:类加载时创建唯一实例
    private static final HungrySingleton INSTANCE = new HungrySingleton();
    
    // 2. 私有构造函数:禁止外部new
    private HungrySingleton() {}
    
    // 3. 公有静态方法:返回实例
    public static HungrySingleton getInstance() {
        return INSTANCE;
    }
}

方式 2:懒汉式(线程不安全→线程安全优化)

"懒汉式" 在首次调用 getInstance() 时才创建实例,节省内存,但需额外处理线程安全(否则多线程下可能创建多个实例)。

线程安全优化版(双重检查锁定)

csharp 复制代码
public class LazySingleton {
    // 1. 私有静态成员变量:volatile防止指令重排序(关键!)
    private static volatile LazySingleton INSTANCE;
    
    // 2. 私有构造函数
    private LazySingleton() {}
    
    // 3. 公有静态方法:双重检查锁定
    public static LazySingleton getInstance() {
        // 第一次检查:避免已创建实例时的锁竞争
        if (INSTANCE == null) {
            synchronized (LazySingleton.class) {
                // 第二次检查:防止多线程同时进入第一个检查后重复创建
                if (INSTANCE == null) {
                    INSTANCE = new LazySingleton();
                }
            }
        }
        return INSTANCE;
    }
}

方式 3:静态内部类(推荐,线程安全且延迟加载)

利用 Java "静态内部类加载时机" 的特性:内部类在被调用时才加载,既实现延迟加载,又天然避免线程安全问题(类加载过程由 JVM 保证线程安全)。

csharp 复制代码
public class StaticInnerClassSingleton {
    // 1. 私有构造函数
    private StaticInnerClassSingleton() {}
    
    // 2. 静态内部类:存储唯一实例
    private static class SingletonHolder {
        private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
    }
    
    // 3. 公有静态方法:调用内部类的实例
    public static StaticInnerClassSingleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

5. 应用场景

  • 系统中只能有一个实例的对象,如:

    • 数据库连接池(DataSource);
    • 配置文件管理器(读取全局配置);
    • 日志工具类(避免多实例写入日志时的冲突);
    • 操作系统的任务管理器、回收站。

6. 注意事项

  • 线程安全:懒汉式必须处理线程安全,否则多线程环境下会破坏 "单例" 特性;
  • 序列化问题 :若单例类实现 Serializable,需重写 readResolve() 方法,否则反序列化会创建新实例;
  • 反射攻击:私有构造函数可通过反射被调用,需在构造函数中添加判断(若实例已存在则抛异常)。
相关推荐
Goldn.4 小时前
Java核心技术栈全景解析:从Web开发到AI融合
java· spring boot· 微服务· ai· jvm· maven· hibernate
李慕婉学姐5 小时前
【开题答辩过程】以《基于Android的出租车运行监测系统设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·后端·vue
m0_740043735 小时前
SpringBoot05-配置文件-热加载/日志框架slf4j/接口文档工具Swagger/Knife4j
java·spring boot·后端·log4j
编织幻境的妖5 小时前
SQL查询连续登录用户方法详解
java·数据库·sql
未若君雅裁6 小时前
JVM面试篇总结
java·jvm·面试
kk哥88996 小时前
C++ 对象 核心介绍
java·jvm·c++
招风的黑耳6 小时前
我用SpringBoot撸了一个智慧水务监控平台
java·spring boot·后端
xunyan62346 小时前
面向对象(下)-接口的理解
java·开发语言
程序员游老板6 小时前
基于SpringBoot3+vue3的爱心陪诊平台
java·spring boot·毕业设计·软件工程·课程设计·信息与通信
期待のcode6 小时前
Springboot核心构建插件
java·spring boot·后端