【Java】单例模式详解与实践

news2024/10/9 12:49:42

欢迎浏览高耳机的博客

希望我们彼此都有更好的收获

感谢三连支持!

单例模式 Singleton是一种常用的软件模式,确保一个类只有一个实例,并提供一个全局访问方法来获取这个实例。这种模式广泛应用于需要控制实例化次数的场景,如数据库连接池、配置管理、日志记录等。本文我们将重点讨论懒汉模式的实现. 

  

单例模式的常用实现方式

饿汉模式:当你使用搜索引擎搜索词条时,不论你是否上下浏览或者翻页,搜索引擎将加载全部的搜索结果,此时在类加载时就完成了实例化。通常这种模式比较消耗资源和时间.

懒汉模式:当你使用搜索引擎搜索词条时,浏览器只会加载当前屏幕页面所能展示内容的上限.只有当你上下浏览,缩放或者进行翻页操作时,才会加载更多结果.这就是在需要时才创建实例。这样做可以加快加载速度,节省了时间和资源.

 饿汉模式单例实现

//饿汉模式实现的基本单例模式

class Singleton {
    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }

    // 单例模式的最关键部分.
    private Singleton() { }
}

 

private SingletonLazy() { } 这行代码的作用是定义一个私有的构造函数。这是实现单例模式的一个关键步骤,具体作用如下:

限制实例化:通过将构造函数设置为私有(private),可以防止外部代码通过new关键字直接创建该类的实例。这样可以确保只有单例类自己能够创建其对象,控制了实例的创建过程。

保证唯一性:单例模式的核心目标是确保一个类只有一个实例。通过私有化构造函数,可以防止外部通过构造函数创建多个实例,保证了实例的唯一性。

控制创建时机:在单例模式中,通常在内部提供一种特殊的方法(如getInstance())来控制实例的创建时机。这意味着实例的创建可以被延迟,直到真正需要时才进行,这有助于优化资源的使用。

封装和安全性:私有构造函数还有助于封装类的实现细节,确保类的用户不能改变实例的创建方式,增加了代码的安全性。

在单例模式的实现中,私有构造函数通常与静态方法(如getInstance())结合使用,该静态方法负责检查是否已经存在一个实例,如果不存在,则创建一个新实例并返回。这样,无论何时何地调用getInstance(),都只会得到同一个实例。

 懒汉模式单例实现 

class SingletonLazy {
    // 此处先把这个实例的引用设为 null, 先不着急创建实例.
    private static SingletonLazy instance = null;

    public static SingletonLazy getInstance() {

                if (instance == null) {
                    instance = new SingletonLazy();
                }
     
        return instance;
    }

    private SingletonLazy() { }
}

在这个懒汉模式单例的基本实现中,其实存在着严重的线程安全问题 !

在多线程环境下,如果两个或更多的线程同时执行getInstance()方法,并且此时instance变量为null,那么每个线程都可能看到instancenull,并且每个线程都可能创建一个新的实例。这样就违背了单例模式的原则,即只创建一个实例。为了确保线程安全,我们必须采取措施:

class SingletonLazy {
    // 此处先把这个实例的引用设为 null, 先不着急创建实例.
    private static volatile SingletonLazy instance = null;
    private static Object locker = new Object();

    public static SingletonLazy getInstance() {
        // 在这个条件中判定当前是否应该要加锁.
        if (instance == null) {
            synchronized (locker) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }

    private SingletonLazy() { }
}
 关键点解释

volatile关键字:确保多线程环境下的可见性和禁止指令重排序。

双重校验锁:第一次检查instance是否为null,避免不必要的同步;第二次检查确保只有一个实例被创建。

同步块:确保只有一个线程可以进入创建实例的代码块。

测试单例 

 验证创建的单例对象是否为同一对象:

public class Demo16 {
    public static void main(String[] args) {
        SingletonLazy s1 = SingletonLazy.getInstance();
        SingletonLazy s2 = SingletonLazy.getInstance();
        System.out.println(s1 == s2);
    }
}

 

单例模式总结

控制实例化次数:节约资源,提高性能。

全局访问点:便于管理和访问。

全局状态:可能导致代码难以测试和维护。

线程安全问题:需要额外处理多线程环境下的同步问题。

通过本文的介绍,我们了解了单例模式的理论基础、实现方式、线程安全问题。掌握单例模式不仅能够帮助我们写出更高效、更优雅的代码,还能够提升我们的系统设计能力。在未来的开发工作中,合理运用单例模式,将使我们的设计更加成熟和稳定。 


希望这篇博客能为你理解单例模式提供一些帮助。

如有不足之处请多多指出。

我是高耳机。

 

 

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

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

相关文章

昇思MindSpore进阶教程--数据处理性能优化(中)

大家好,我是刘明,明志科技创始人,华为昇思MindSpore布道师。 技术上主攻前端开发、鸿蒙开发和AI算法研究。 努力为大家带来持续的技术分享,如果你也喜欢我的文章,就点个关注吧 shuffle性能优化 shuffle操作主要是对有…

VMware ESXi 8.0U3 集成 AQC 网卡定制版更新 OEM BIOS 2.7 支持 Windows Server 2025

VMware ESXi 8.0U3 集成 AQC 网卡定制版更新 OEM BIOS 2.7 支持 Windows Server 2025 VMware ESXi 8.0U3 macOS Unlocker & OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版) 发布 ESXi 8.0U3 集成驱动版,在个人电脑上运行企业级工作负载 请访问原文链接&…

数字化转型引领新时代:从架构到产品的全链路创新解析

在当前瞬息万变的商业环境中,数字化转型已经成为各类组织的核心战略手段。本文从数字化专业知识体系 (DPBOK) 中提炼出最具价值的核心观点,详细分析了数字化转型对企业的影响、实现路径,以及如何通过技术创新、文化转变和管理优化&#xff0c…

YOLO11涨点优化:注意力魔改 | 新颖的多尺度卷积注意力(MSCA),即插即用,助力小目标检测

💡💡💡本文全网首发独家改进:多尺度卷积注意力(MSCA),有效地提取上下文信息,新颖度高,创新十足。 💡💡💡本文改进:分别加入…

协议转换器——连接未来生产的纽带

智能制造作为制造业前沿趋势,面临不同设备和系统间通信协议不兼容导致的信息交换困难。我们自主研发的MG协议转换器作为桥梁与纽带,实现了不同设备和系统间的顺畅数据交换,提高了生产效率,降低了生产成本。在工业自动化和能源管理…

【d63】【Java】【力扣】142.训练计划IV

思路 出口: 1. l1 null && l2 null 2. 一个null 一个不为bull,但是还需要向下递归 每层: 判断哪一个更小,更小的放进新的数组 代码 递归实现 /*** Definition for singly-linked list.* public class ListNode {* int va…

Python酷库之旅-第三方库Pandas(138)

目录 一、用法精讲 621、pandas.plotting.lag_plot方法 621-1、语法 621-2、参数 621-3、功能 621-4、返回值 621-5、说明 621-6、用法 621-6-1、数据准备 621-6-2、代码示例 621-6-3、结果输出 622、pandas.plotting.parallel_coordinates方法 622-1、语法 622-…

labview和QT编程

Labview LabView所面向的并非传统意义上的程序员。他的所有功能都可以通过组合某些组件来完成。程序的流程控制,【www.zhugedz.com】比如循环之类的也是通过画图一样的操作来做的。 所有的程序功能几乎都可以通过鼠标来构造出来。优点是做一个能运行的程序非常简单…

有关环境变量的一些话题-----环境变量的分类

配置环境变量的文件: 环境变量的分类: 环境变量加载顺序 一般添加系统环境变量,修改/etc/profile文件,如果操作失误,删除重要配置,影响系统运行。 centos7版本中 /etc/profile 默认扫描路径 /etc/profile.…

微信小程序处理交易投诉管理,支持多小程序,一键授权模式

大家好,我是小悟 1、问题背景 玩过微信小程序生态的,或许就有这种感受,如果收到投诉单,不会及时通知到手机端,而是每天早上10:00向小程序的管理员及运营者推送通知。通知内容为截至前一天24时该小程序账号内待处理的交…

188页企业数字化转型建设方案(数据中台、业务中台、AI中台)

建设背景 随着信息技术的不断进步,企业面临着前所未有的机遇与挑战。数字化转型不仅是技术层面的革新,更是企业运营模式和思维方式的深刻变革。通过数字化转型,企业可以实现资源的最优配置、业务的精准量化以及管理的智能化,从而…

服装生产管理:SpringBoot框架的高效实现

3 系统分析 3.1 可行性分析 可行性分析是该平台系统进行投入开发的基础第一步,必须对其进行可行性分析才能够降低不必要的需要从而使资源合理利用,更具有性价比和降低成本,同时也是系统平台的成功的未雨绸缪的一步。 3.1.1 技术可行性 技术…

【网易buff】无法登录steam,显示创建账号,无法解决

手机速度大提升!浏览器内核WebView升级指南 WebViewUpgrade 心血来潮想通过网易buff花钱快乐一下,结果发现这app有问题,是因为webview版本问题,这开发真傻逼啊 发现经过 在buff重新登陆Steam的时候,页面只有创建账号…

服装生产管理:SpringBoot框架的创新设计

4 系统设计 4.1 系统结构设计 在结构设计过程中,首先对系统进行需求分析,然后进行系统初步设计,将系统功能模块细化,具体分析每一个功能模块具体应该首先哪些功能,最后将各个模块进行整合,实现系统结构的…

基于SSM的学生社团管理系统—计算机毕业设计源码37391

目 录 摘要 1 绪论 1.1研究背景 1.2研究目的和意义 1.3系统开发技术的特色 1.4 ssm框架介绍 1.5论文结构与章节安排 2 学生社团管理系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1数据流程 2.3.2业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能…

Authentication Lab | User Agent Strings

关注这个靶场的其它相关笔记:Authentication Lab —— 靶场笔记合集-CSDN博客 0x01:User Agent Strings 前情提要 在某些特殊的场景中,服务端会假定客户端可以信任,并根据客户端告知它的内容做出身份验证的决策。 然而&#xff…

Android开发banner效果

Android开发banner效果 banner在每个app都会有的 一、思路: 用viewpager也可以做。但我是引进第三方库的 二、效果图: 三、关键代码: // 联系:893151960 public class MainActivity extends AppCompatActivity {private Bann…

【MATLAB代码】基于RSSI原理的蓝牙定位程序(N个锚点、三维空间),源代码可直接复制

文章目录 介绍主要功能技术细节适用场景程序结构运行截图源代码详细教程:基于RSSI的蓝牙定位程序1. 准备工作2. 代码结构2.1 清理工作环境2.2 定义参数2.3 生成锚点坐标2.4 定义信号强度与距离的关系2.5 模拟未知点的位置2.6 定位函数2.7 绘图2.8 输出结果2.9 定义定位函数3. …

RDD的介绍、RDD的特点、创建RDD数据

文章目录 1. RDD介绍1.1 Spark开发方式1.1.1 交互式开发1.1.2 脚本式开发 1.2 Spark支持的开发语言1.3 RDD介绍 2. RDD特性3. 创建RDD数据3.1 Python数据转化为RDD3.2 文件数据HDFS转化为RDD3.3 RDD分区3.4 小文件数据读取 1. RDD介绍 1.1 Spark开发方式 1.1.1 交互式开发 通…

【LeetCode】动态规划—712. 两个字符串的最小ASCII删除和(附完整Python/C++代码)

动态规划—712. 两个字符串的最小ASCII删除和 前言题目描述基本思路1. 问题定义2. 理解问题和递推关系3. 解决方法3.1 动态规划方法3.2 空间优化的动态规划 4. 进一步优化5. 小总结 代码实现PythonPython3代码实现Python 代码解释 CC代码实现C 代码解释 总结: 前言 在字符串处…