深入理解java设计模式之单例模式

目录

  • 概述
    • 单例模式是什么
    • 单例模式的使用场景
    • 单例模式的优缺点
  • 单例模式的几种实现方式
    • 饿汉式
    • 懒汉式
    • 双重检查锁定机制
    • 静态内部类
    • 枚举
    • 使用容器
  • 几种可能破坏单例类的方法
    • 多线程环境下的竞争条件
    • 使用反射机制
    • 使用序列化
    • 多个类加载器

概述

单例模式是什么

定义:单例模式确保一个类在应用程序中只有一个对象实例存在,并提供一种全局访问该实例的方式

单例模式的使用场景

这种模式适用于需要共享资源或需要集中管理某些状态或配置的场景。通过使用单例模式,可以确保全局只有一个实例,避免了多个实例导致的资源浪费或状态不一致的问题。

同时,其他部分的代码只能通过单例类提供的公共访问点来获取该实例,从而限制了对实例的直接访问。

单例模式的优缺点

优点:

  1. 确保只有一个实例:单例模式确保在整个应用程序中只有一个实例存在,这对于某些资源的共享和状态的集中管理非常有用。
  2. 全局访问点:通过单例模式,可以提供一个公共访问点,让其他部分的代码可以方便地访问该实例。
  3. 节省资源:由于只有一个实例存在,可以避免重复创建对象,从而节省了系统资源的使用。
  4. 状态一致性:单例模式可以确保实例的状态始终保持一致,避免了多个实例之间的状态冲突。

缺点:

  1. 难以扩展:由于单例模式只允许存在一个实例,因此在需要扩展功能时可能会遇到困难。如果需要更多的实例或者多态的行为,单例模式可能不是最佳选择。
  2. 全局状态:由于单例模式的实例是全局可访问的,可能会导致全局状态的增加,增加了代码的复杂性和维护难度。
  3. 对象生命周期管理:单例模式的实例在整个应用程序的生命周期中存在,可能会导致对象的生命周期变得复杂,增加了对对象生命周期管理的要求。

单例模式的几种实现方式

饿汉式

饿汉式顾名思义,饥不择食,在类加载时就创建了单例对象,并在整个生命周期中保持不变。饿汉式的特点是在类加载时就创建实例,因此它是线程安全的。

public class Singleton {private static final Singleton INSTANCE = new Singleton();private Singleton() {// 私有的构造方法,防止外部实例化}public static Singleton getInstance() {return INSTANCE;}
}

在饿汉式单例模式中,INSTANCE是一个私有静态常量,它在类加载时就被实例化,并且保持为单例对象。私有的构造方法确保其他类无法直接实例化该类。

通过getInstance()方法,可以获取到该单例对象的实例。由于在类加载时就创建了实例,因此在多线程环境下也不会有线程安全问题

饿汉式单例模式的优点是实现简单,线程安全,能够保证在任何时候都只有一个实例存在
但它也有一些缺点,例如在应用启动时就创建实例,可能会增加启动时间;如果该单例对象的创建过程比较耗时,对应用的性能有一定影响。另外,由于实例是在类加载时创建的,无法实现按需创建实例的延迟加载。因此,饿汉式适用于实例创建耗时较少且在应用启动时就需要使用的情况

懒汉式

懒汉式是单例模式的另一种实现方式,它延迟实例化对象,直到第一次使用时才进行创建。懒汉式的特点是在需要时才创建实例,但需要注意线程安全的处理

public class Singleton {private static Singleton INSTANCE;private Singleton() {// 私有的构造方法,防止外部实例化}//同步方法public static synchronized Singleton getInstance() {if (INSTANCE == null) {INSTANCE = new Singleton();}return INSTANCE;}//同步代码块public static Singleton getInstance() {if (INSTANCE == null) {synchronized (Singleton.class) {INSTANCE = new Singleton();}}return INSTANCE;}
}

INSTANCE是一个私有静态变量,它在第一次调用getInstance()方法时进行实例化。通过synchronized关键字,确保在多线程环境下只有一个线程可以进行实例化操作,从而保证线程安全性。

懒汉式单例模式的优点是在需要时才创建实例,避免了在应用启动时就进行实例化的开销。然而,需要注意线程安全性的处理,以及对性能的影响。懒汉式适用于实例创建较为耗时且在应用中可能不一定会被使用到的情况。

双重检查锁定机制

懒汉式单例模式引入了同步锁的机制,可能会在多线程环境下影响性能。每次调用getInstance()方法时都需要获取锁,即使实例已经被创建。这种同步的开销在高并发场景下可能会成为性能瓶颈。

为了解决性能问题,可以使用双重检查锁定机制,避免每次调用getInstance()都进行同步操作。

public class Singleton {private static volatile Singleton INSTANCE;

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

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

相关文章

Java中Transactional在不同方法间的穿透性,rollbackFor参数含义

哈喽,大家好,我是木头左! 在Java开发中,经常会遇到需要在一个事务中执行多个操作的场景。为了确保这些操作的原子性,可以使用Spring框架提供的Transactional注解来实现事务管理。然而,在实际开发过程中&…

LeetCode刷题之HOT100之验证二叉搜索树

1、题目描述 2、逻辑分析 要求给定的根节点是否是有效的二叉树。有效的二叉搜索树定义如上。那么如何求解呢?题解给出了两张求解方法:递归、中序遍历。这边倾向于中序遍历,中序遍历后的二叉树是升序排序的,以这个性质即可解题。 …

Prometheus——部署详解

目录 一、Prometheus Server端安装和相关配置 1.上传安装包并解压 2.配置系统启动文件 3.启动 二、部署Node Exporters监控系统指标 三、监控Mysql配置示例 1.Mysql服务器操作 2.Prometheus服务器操作 四、监控Nginx配置示例 1.在Nginx服务器操作 2.Prometheus服务器…

HTML列表和表格标签

目录 1.列表标签 1.1无序列表 1.2有序列表 1.3定义列表 2. 表格标签、 2.1表格标签的属性 2.2合并单元格 1.列表标签 1.1无序列表 <ul>: [type 属性&#xff1a; disc( 实心圆点 )( 默认 ) 、 circle( 空心圆圈 ) 、 square( 实心方块 )] <li>: 列表中…

vue+java实现简易AI问答组件(基于百度文心大模型)

一、需求 公司想要在页面中加入AI智能对话功能&#xff0c;故查找免费gpt接口&#xff0c;最终决定百度千帆大模型&#xff08;进入官网、官方文档中心&#xff09;&#xff1b; 二、主要功能列举 AI智能对话&#xff1b;记录上下文回答环境&#xff1b;折叠/展开窗口&#…

用Qt 中的QPainter类画时钟

在Qt中&#xff0c;我们可以通过QPainter类来绘制各种图形&#xff0c;包括时钟指针。以下是一个简单的例子&#xff0c;展示了如何在Qt中绘制一个简单的时钟指针。 #include <QPainter> #include <QWidget> #include <QTimer> #include <QTime>class…

管道(channel)select

select功能&#xff1a;解决多个管道的选择问题&#xff0c;也可以叫多路复用&#xff0c;可以从多个管道中随机公平的选择一个来执行 case后面必须进行的是io操作&#xff0c;不能是等值&#xff0c;随机去选择一个io操作 default防止select被阻塞&#xff0c;加入default 只…

使用MATLAB对地铁站、公交站等求解最短路径

使用MATLAB对城市的地铁站、公交站等站点&#xff0c;根据站点的经纬度坐标和彼此之间的权重&#xff0c;求解其最短路径、途径站点和路程 已知的数据如图&#xff0c;是西安市地铁站点的数据&#xff0c;保存在一个Excel里 如图&#xff0c;每列的内容都在上面&#xff0c;不…

滚动条样式

/*滚动条*/ //滚动条没有滑块的轨道部分. ::-webkit-scrollbar-track-piece {background: #fff;border-radius: 0px;opacity: 1;border: 1px solid #D9D9D9; } //整个滚动条 ::-webkit-scrollbar {width: 8px;height: 8px;background-color: transparent; } //滚动条上的滚动滑…

经常加班却不给加班费,我又不想离开这个单位,该怎么办?

经常加班却不给加班费&#xff0c;我又不想离开这个单位&#xff0c;该怎么办&#xff1f; --#李秘书讲写作#教你如何在维护权益与保持工作稳定间找到平衡&#xff1f; 在现代社会中&#xff0c;加班已经成为许多职场人士的常态。你也许也不例外&#xff0c;每天都在忙碌的工作…

Python教程:机器学习 - 百分位数(4)

什么是百分位数&#xff1f; 统计学中使用百分位数&#xff08;Percentiles&#xff09;为您提供一个数字&#xff0c;该数字描述了给定百分比值小于的值。 例如&#xff1a;假设我们有一个数组&#xff0c;包含住在一条街上的人的年龄。 ages [5,31,43,48,50,41,7,11,15,3…

深入理解服务器路由功能:配置与应用详解

在现代网络结构中&#xff0c;服务器不仅仅是提供数据和服务的中心节点&#xff0c;它们还经常承担着路由的角色&#xff0c;负责在不同网络之间转发数据包。这一过程依赖于服务器的路由功能&#xff0c;通过精确的路由表配置和管理&#xff0c;确保数据能够高效、准确地到达目…

SSL协议在实际生活中有哪些应用实例?

SSL协议的实际应用案例 SSL&#xff08;Secure Sockets Layer&#xff09;协议是一种网络通信协议&#xff0c;用于在客户端和服务器之间建立加密链接&#xff0c;以确保数据在传输过程中的安全性。尽管SSL协议已被TLS&#xff08;Transport Layer Security&#xff09;协议所取…

AMS(ActivityManagerService)源码解析,Activity是如何被打开的

AMS解析&#xff0c;Activity是如何被打开的 前言总结1. PMS保存App缩略信息2. startActivity发送请求3. AMS从PMS获取目标Activity的相关信息3.1 AMS部分3.2 PMS部分 4. AMS操作Activity返回栈&#xff0c;将目标Activity调用resume5. AMS将目标页面信息发给ActivityThread6. …

STM32学习笔记(二)--GPIO通用输入输出口详解

&#xff08;1&#xff09;配置步骤1.使用RCC开启GPIO时钟2.使用GPIO_Init函数初始化GPIO3.使用输入或输出的函数等来控制GPIO 其中涉及外设有RCC、GPIO &#xff08;2&#xff09;代码示例 案例1&#xff08;设置PA0为推挽输出&#xff09; RCC_APB2PeriphClockCmd(RCC_APB2…

使用Spring Cloud设计电商系统架构

在当今互联网高速发展的时代&#xff0c;电子商务系统成为了商家与用户互动的主要方式之一。为了能够更好地应对高并发、可扩展性、灵活性等需求&#xff0c;微服务架构逐渐成为设计电商系统的首选方案。Spring Cloud作为一个成熟的微服务框架&#xff0c;为开发人员提供了一整…

后端开发面试题4(附答案)

前言 在下首语言是golang,所以会用他作为示例。 原文参见 @arialdomartini的: Back-End Developer Interview Questions 语言相关问题 1. 告诉我你的首选语言的三个最坏的缺陷。 Golang虽然在很多方面表现出色,但它并非完美无缺,根据已有的讨论和批评,以下是Go语言被广泛…

深入浅出:面向对象软件设计原则(OOD)

目录 前言 1.单一责任原则&#xff08;SRP&#xff09; 2.开发封闭原则&#xff08;OCP&#xff09; 3.里氏替换原则&#xff08;LSP&#xff09; 4.依赖倒置原则&#xff08;DIP&#xff09; 5.接口分离原则&#xff08;ISP) 6.共同封闭原则&#xff08;CCP&#xff09…

Android替换默认的按键音

替换audio_assets.xml文件 此文件在AudioService.java被调用 <!--文件位置 /frameworks/base/core/res/res/xml/--> <audio_assets version"1.0"><group name"touch_sounds"><asset id"FX_KEY_CLICK" file"Effect…

用idea将java文件打成jar包

一、用idea将java文件打成jar包 1、在idea上选择file—Project Structure 2、Artifacts —点–JAR—From modules with dependencies 3、选择要打包的java文件 4、Build — Build Artifacts 5、找到刚才添加的Artifacts直接Build 6、生成jar包文件