一文彻底学会单例模式

news2024/10/9 17:20:03

一、为什么使用单例模式?

单例模式是一种创建型设计模式,目的是确保一个类在应用程序中只有一个实例,并提供全局访问点。以下是使用单例模式的几个好处

  • 资源节省:对于需要频繁创建和销毁的对象,比如数据库连接或日志记录器,使用单例模式可以节约系统资源。
  • 全局访问:提供一个全局的访问点,便于访问共享资源。
  • 控制实例数量:确保一个类只有一个实例,避免对资源的多重占用。

二、单例模式是什么?

单例模式限制类的实例化次数为一次,并通过提供一个静态方法来获取该实例。下面是几种常见的实现方式:

  • 懒汉式:实例在第一次使用时创建,不适用于多线程环境。
  • 饿汉式:类加载时即创建实例,线程安全。
  • 双重检查锁定:结合懒汉和饿汉的优点,适用于多线程。
  • 静态内部类:利用JVM的类加载机制实现线程安全和延迟加载。

三、怎么用单例模式?

一、懒汉式(线程不安全)

这种方式只适合单线程使用,多线程下有会实例化多个对象

public class Single {
    private static Single instance;
 
    private Single(){
        System.out.println("实例化Single对象");
    }
    public static Single getInstance(){
        if (instance == null) instance = new Single();
        return instance;
    }
}
public class test {
    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            Single.getInstance();
        }
    }
}
测试结果:
    /*
    实例化Single对象
    Process finished with exit code 0
    */
二、懒汉式(线程安全)

只需添加一个synchronized 关键字即可,也就是常见的加锁操作。

public class Single {
    private static Single instance;
 
    private Single(){
        System.out.println("实例化Single对象");
    }
    public synchronized static Single getInstance(){
        if (instance == null) instance = new Single();
        return instance;
    }
}
public class test {
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(()->{
                Single.getInstance();
            }).start();
        }
    }
}
测试结果:
    /*
    实例化Single对象
    Process finished with exit code 0
    */

在多线程环境中使用 synchronized 可以确保实例只被创建一次,但它会导致系统资源的浪费。假设我们进行10次调用,每次都会经过加锁过程,实际上我们只需在第一次实例化时加锁。后续的调用仅需要进行逻辑判断,而不必再实例化对象。因此,我们可以引入一种优化方法,减少锁的使用频率,也就是在类加载时直接实例化对象。

三、饿汉式

在饿汉式单例模式中,类的实例是在类加载时就被创建的,这样确保了线程安全和唯一性,但也可能导致资源浪费,因为无论是否需要这个实例,都会在启动时被创建。

public class Single {
   // 在类加载时就创建实例 无论使用不使用 都会创建  会造成资源浪费
    private static final Singleton instance = new Singleton();
    private static Single instance = new Single();
 
    private Single(){
        System.out.println("实例化Single对象");
    }
    public  static Single getInstance(){
        return instance;
    }
}
四、双重检查锁定:结合懒汉和饿汉的优点,适用于多线程。

双重检查锁定旨在减少不必要的同步,提高性能。它结合了懒汉式和饿汉式的优点:

  • 懒汉式加载:只有在需要时才创建实例。
  • 线程安全:通过同步块和双重检查,确保多线程环境下实例的唯一性。
public class Singleton {
    private volatile static Singleton instance;

    private Singleton() {}

    public static Singleton getInstance() {
    //第一次检查:避免不必要的同步,提高性能。如果实例已存在,直接返回。
        if (instance == null) {
            synchronized (Singleton.class) {
            //第二次检查:在同步块内再次检查,确保实例未被其他线程创建。只在第一次时创建实例。
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
五、静态内部类。

静态内部类利用JVM类加载机制,在类加载时并不会立即创建实例,而是在调用 getInstance() 方法时才创建,实现了延迟加载和线程安全。

public class Singleton {
    private Singleton() {}

    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}

适用场景:
单例模式适用于需要频繁创建和销毁的对象、创建对象耗时较多但又经常用到的对象、工具类对象等。
优缺点:

  • 优点:内存中只有一个实例,减少内存开销,避免多重占用。
  • 缺点:不利于扩展,单例类职责过重,在一定程度上违反了单一职责原则。
    注意事项:
  • 在多线程环境下,要确保线程安全。
  • 如果使用反射机制或者序列化机制,需要额外处理以确保单例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2199565.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

用友crm客户关系管理config/fillbacksettingedit.php接口存在SQL注入漏洞

免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失,均由使用者本人负责,所产生的一切不良后果与文章作者无关。该文章仅供学习用途使用。 1. 用友crm客户关系管理简介 微信公众号搜索:南风漏…

LangChain4j系列—Java AI框架LangChain4j快速入门

一、概述 LangChain4j于2023年初在ChatGPT的炒作中开始开发。我们注意到&#xff0c;与众多的Python和JavaScript LLM库和框架相比&#xff0c;缺少Java对应项&#xff0c;我们必须修复它&#xff01;尽管“LangChain”是以我们的名义命名的&#xff0c;但该项目融合了LangCha…

UEFI学习笔记(十):系统表与ACPI表的遍历

一、概述 在 UEFI 系统表中&#xff0c;有几个关键的表用于提供系统信息、服务和硬件抽象。这些表可以通过 EFI_SYSTEM_TABLE 访问&#xff0c;常见的 UEFI 系统表如下&#xff1a; 1、EFI_SYSTEM_TABLE (系统表) EFI_SYSTEM_TABLE 是一个指针&#xff0c;包含多个服务和系统…

电力电子技术03 AC-DC整流器(1)---AC-DC整流器概述

一、AC-DC整流器概述 1.AC-DC整流器简介 AC-DC整流器是将交流电&#xff08;AC&#xff09;转换为直流电&#xff08;DC&#xff09;的电力电子设备&#xff0c;它在许多电子设备中至关重要&#xff0c;尤其是需要稳定直流电源的应用场景&#xff0c;如电源适配器、电脑电源、…

VSCode中添加自定义代码片段

目录 VSCode中添加自定义代码片段 基本操作 辅助工具 VSCode中添加自定义代码片段 基本操作 打开Visual Studio Code设置&#xff0c;选择Snippets 在弹出的窗口中选择新建全局片段文件 如果只想为当前工作目录设置片段文件则选择第二个 输入新全局片段文件的名称 这个文件…

Redis学习(十二)连接数不足报错及分析修复:ERR max number of clients reached.

目录 一、问题介绍二、问题分析2.1 redis-cli 登录2.2 info clients 查看连接数情况2.3 client list 查看具体连接情况2.4 分析连接空闲时长2.5 client list 根据客户端IP统计连接数 三、问题结论和解决3.1 问题结论&#xff1a;3.2 解决方案①&#xff1a;优化程序3.3 解决方案…

execl表格批量换行问题

我拿到了一份execl表格。需要用代码去读每一行。 当我点击wps中的换行的时候。显示已经换行了。 但是我双击图表的时候&#xff0c;显示换行并没有生效。 还是在cell单元格里有很多行。 此时&#xff0c;ctrlf打开替换按钮。 选择替换的内容&#xff1a;altenter 按住alten…

轨迹预测升级:如何让自动驾驶汽车从意图与风险中真正读懂“人心”?

导读&#xff1a; 本篇文章提出了一种基于联合预测的轨迹预测模型&#xff0c;包括交互模块、意图模块和风险评估模块。实验结果表明&#xff0c;本文模型在正常场景中保持高准确性&#xff0c;并且展现了在事故场景中应对具有挑战性或者突发情况的潜力。©️【深蓝AI】编译…

重学SpringBoot3-集成Redis(九)之共享Session

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;九&#xff09;之共享Session 1. 为什么需要 Session 共享2. Spring Session 和 Redis 的集成2.1. 引入依赖2.2. 配置 Redis 连接…

车辆重识别(2022ACM SIGGRAPH调色板:图像到图像的扩散模型)论文阅读2024/10/09

[2] Palette: Image-to-Image Diffusion Models ( ACM SIGGRAPH 2022) 作者&#xff1a;Chitwan Saharia、William Chan、Huiwen Chang 单位&#xff1a;Google Research, Brain Team 摘要&#xff1a; 本文基于条件扩散模型开发了一个统一的图像到图像翻译框架&#xff0c;并…

无人机避障——4D毫米波雷达点云滤波去噪(四)

噪声的来源&#xff1a; 对于4D毫米波雷达的前后两帧点云数据进行去噪&#xff0c;可以采用多种方法。首先&#xff0c;需要了解点云数据的噪声来源&#xff0c;可能是由于硬件限制、环境干扰或目标本身的反射特性等因素造成的。噪声点通常包括漂移点、孤立点、冗余点和混杂点…

【通过zip方式安装mysql服务】

通过zip方式安装mysql服务 Mysql安装包下载mysql安装及环境配置1.解压缩配置环境变量初始化mysql配置安装mysql服务启动MySQL服务连接mysql修改root用户密码 Mysql安装包下载 通过访问mysql官网下载&#xff1a;mysql下载地址 mysql安装及环境配置 1.解压缩 下载完成后&am…

YOLOv10改进策略【注意力机制篇】| GAM全局注意力机制: 保留信息以增强通道与空间的相互作用

一、本文介绍 本文记录的是基于GAM注意力模块的YOLOv10目标检测改进方法研究。GAM注意力模块通过3D排列和重新设计的子模块&#xff0c;能够在通道和空间方面保留信息&#xff0c;避免了先前方法中由于信息减少和维度分离而导致的全局空间-通道交互丢失的问题。本文利用GAM改进…

『网络游戏』角色创建界面逻辑【11】

创建代码&#xff1a;CreateWnd.cs 编写脚本&#xff1a;CreateWnd.cs 绑定脚本 修改脚本&#xff1a;LoginWnd.cs 绑定事件 修改脚本&#xff1a;Constans.cs 修改脚本&#xff1a;LoginSys.cs 修改脚本&#xff1a;LoginWnd.cs 拖拽框选 运行项目 - 点击开始进入创建角色界面…

柯桥外语培训韩语学习考级韩语中TOPIK常用语法表达

-기 위해서는 -는 것이 좋다 为了......&#xff0c;......比较好 -는 것보다는 -는 것이 좋다 比起......&#xff0c;......比较好 -(으)려면 -아/어/야 한다 如果想......的话&#xff0c;得...... -왜냐하면 -기 때문이다 因为...... -그 이유는 -기 때문이다 理由是…

TinyOS 点对基站通信

文章目录 一、前言1.1 发包的BlinkToRadio的数据包格式 二、混淆基站源码分析2.1 Makefile2.2 组件连接2.3 主逻辑代码 一、前言 1.1 发包的BlinkToRadio的数据包格式 如下&#xff0c;注意&#xff1a;AM层类型(1byte)即handlerID使可以在组件中修改的。 二、混淆基站源码…

专访:青年制片人林苏楠给影视行业新人的建议

近十年&#xff0c;对影视行业抱有浓厚兴趣&#xff0c;并进入专业院校学习的年轻人越来越多。但他们中的很多人毕业后却选择了其他行业&#xff0c;或者从事影视行业几年后决定转行。这其中的缘由似乎一部分来源于年轻创作者对真实的影视市场的不了解和不适应。 我们这次采访…

GC9118S替代TMI8118的优势分析,可应用在牙刷,电子锁,医疗设备等产品中

GC9118S作为一种新型集成电路&#xff0c;逐渐被视为TMI8118的理想替代品。以下是GC9118S在多个方面的优势&#xff0c;使其能够有效替代TMI8118。 1. 低功耗设计 GC9118S在功耗方面进行了优化&#xff0c;使其在待机和工作状态下都能显著降低能耗。这对于电池供电的设备&…

SpringBoot高级并发实践:自定义线程池与@Async异步调用深度解析

文章目录 同步编程&异步编程线程池为什么要使用线程池&#xff1f;Spring自定义线程池SpringBoot轻松调用线程池总结 测试demo链接 同步编程&异步编程 在Java并发编程中&#xff0c;同步和异步是两种常见的处理方式。 同步是指多个任务按顺序执行&#xff0c;一个任务的…

虚拟机三种网络配置方式随笔

1.1桥接模式 虚拟机和物理机同时直接连接物理网络&#xff08;均作为独立主机&#xff09; 桥接模式下&#xff0c;虚拟主机与真实主要在VMnet0构成的局域网内通信&#xff0c;同时通过真实主机中的网关与外网通信。由上表可看出&#xff0c;VMnet0直接连接到真实主机的某块真…