当前位置: 首页 > news >正文

【设计模式】单例模式 - 实践

文章目录

  • 【设计模式】单例模式
    • 1、什么是单例模式
    • 2、单例模式实现
      • 2.1 饿汉式(线程安全)
      • 2.2 懒汉式(线程不安全)
      • 2.3 同步方法懒汉式 (线程安全)
      • 2.4 双重检查锁定
        • **1.为什么用 `volatile`?**
        • 2.**双重检查的必要性**
      • 2.5 静态内部类(线程安全)
      • 2.6 枚举单例
      • 各实现方式对比

【设计模式】单例模式

1、什么是单例模式

单例模式(Singleton): 保证整个系统中一个类仅有一个对象实例,并提供一个可以访问它的全局访问点。

2、单例模式实现

2.1 饿汉式(线程安全)

**原理:**在类加载时就创建实例

//饿汉式
public class HungrySingleton
{
private static HungrySingleton instance = new HungrySingleton();
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return instance;
}
}

类中直接定义全局的静态对象的实例并初始化,然后提供一个方法获取该实例对象。优点是实现简单,并且线程安全,缺点也很明显,比如在代码中没有使用这个对象也会创建出一个实例,可能会造成资源浪费。

2.2 懒汉式(线程不安全)

**原理:**首次使用时才创建实例

public class LazySingleton
{
private static LazySingleton instance;
private LazySingleton() {
}
public static LazySingleton getInstance() {
if (instance == null) {
// 多线程可能同时进入此区域
instance = new LazySingleton();
}
return instance;
}
}

做法和饿汉式基本差不多,只是在返回实例对象时加入判断,如果已经创建,直接返回创建好的实例对象,确保首次使用才创建。不过需要注意的是,在进行判断时,多线程情况下的其他线程也可能会进入判断,导致线程不安全。优点是延迟加载,需要用到才会创建,一旦创建就一直使用已经创建好的实例,改善了饿汉式的缺点。

2.3 同步方法懒汉式 (线程安全)

**原理:**通过方法级同步保证线程安全

public class SyncMethodSingleton
{
private static SyncMethodSingleton instance;
private SyncMethodSingleton() {
}
// 方法同步保证线程安全
public static synchronized SyncMethodSingleton getInstance() {
if (instance == null) {
instance = new SyncMethodSingleton();
}
return instance;
}
}

和懒汉式唯一的区别在于获取实例对象方法被synchronized 关键字修饰,相当于锁住整个类对象,同一时刻只允许一个线程进入方法,防止多线程情况下创建多个实例

  • 优点:实现简单且线程安全
  • 缺点:性能差(每次调用都同步)

2.4 双重检查锁定

**原理:**减少同步范围 + volatile禁止指令重排序

public class DCLSingleton
{
// volatile保证可见性和禁止指令重排序
private static volatile DCLSingleton instance;
private DCLSingleton() {
}
public static DCLSingleton getInstance() {
if (instance == null) {
// 第一次检查(无锁)
synchronized (DCLSingleton.class)
{
if (instance == null) {
// 第二次检查(有锁)
instance = new DCLSingleton();
}
}
}
return instance;
}
}

第一次if(instance==null):为了提高代码的执行效率,由于单例模式只要一次创建实例即可,所以当创建了一个实例之后,再次调用getInstance方法就不同进入同步代码块,不用竞争锁。

第二次if(instance==null):这个校验时防止二次创建实例。

  • 优点:高性能线程安全

  • 缺点:实现较复杂

1.为什么用 volatile
  • 禁止指令重排序

    instance = new Singleton()实际分为三步:

    1.分配内存空间

    2.初始化对象

    3.将引用指向内存地址

    若无 volatile,JVM 可能重排序为 1→3→2。此时其他线程可能拿到未初始化的对象(instance != null但对象不完整)。

  • 内存可见性:确保所有线程看到最新的 instance值。

2.双重检查的必要性

2.5 静态内部类(线程安全)

原理:利用类加载机制保证线程安全

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

静态内部类方式利用JVM类加载机制确保线程安全,同时实现懒加载特性(延迟初始化)。核心原理是:静态内部类不会在外部类加载时初始化,只有在显式调用时才会加载

  • 优点:延迟加载 + 无同步开销

  • 缺点:无法防止反射攻击

2.6 枚举单例

**原理:**使用一个只包含单个元素的枚举类型来实现单例模式。

public enum EnumSingleton {
// 唯一实例
INSTANCE;
// 添加逻辑方法
public void doSomething() {
System.out.println("枚举单例方法");
}
}
// 使用方式
EnumSingleton.INSTANCE.doSomething();
  • 优点:绝对单例(防止反射/序列化破坏)

  • 缺点:不够灵活

各实现方式对比

实现方式延迟加载线程安全性能防反射防序列化
饿汉式
懒汉式
同步方法懒汉式低(频繁加锁)
双重检查锁定较高
静态内部类
低(频繁加锁)
双重检查锁定较高
静态内部类
枚举
http://www.wxhsa.cn/company.asp?id=6480

相关文章:

  • ubuntu服务器docker容器启动java项目
  • 【2025最新】企业信息模糊搜索API设计与实践指南
  • 一键搞定本土认证难题,AnalyticDB版Supabase助力AI应用实现支付宝微信登录
  • sumifs根据条件求和
  • ubuntu服务器docker安装部署ngix
  • c++右值引用和移动语义
  • 彩笔运维勇闯机器学习--梯度下降法
  • 作业03
  • 项目管理软件产业革命:从工具升级到生产力范式转移
  • vs code运行Java遇到的输入问题
  • 关于数据跨境,你应该了解的合规难题有哪些?
  • 国内开发者如何选择代码管理平台?三大主流工具深度对比
  • doubletrouble wp复盘
  • VAR算法
  • mysql 万能恢复主从Slave_SQL_Running 是No
  • 刚刚 Java 25 炸裂发布!让 Java 再次伟大
  • go 语言结构和基础语法
  • 详细介绍:Linux--初识网络
  • lua程序调试方法
  • 维保信息查询
  • 人工智能学习路线学习资料整理
  • 软件设计师知识点总结(2023)上
  • 【运维自动化-标准运维】各类全局变量使用说明(中)
  • 提示词工程(Prompt Engineering)是不是“新时代的编程”?
  • python日志记录之logging模块
  • O - Color a Tree
  • 电脑时间改了,软件不能用了
  • OFDM 自适应功率与比特分配
  • 前 k 小问题期末考
  • 1380亿条微博全量数据集,可用于自然语言处理、情感分析、舆情分析、推荐系统、用户行为数据、商业智能、人工智能模型训练、中文文本数据、地理位置信息、时间序列分析、JSON格式、机器学习、文本挖掘等