【设计模式】单例模式Singleton(Java)
文章目录
- 定义
- 类图
- Java经典实现
- 懒汉Lazy Mode:
- 饿汉Eager Mode:
- 在饿汉下的多线程案例
- 在懒汉下的多线程案例
- 总结
定义
单例模式(单件模式)确保一个类只有一个实例,并提供一个全局访问点。——HeadFirst
单例模式通过过防止外部实例化和修改来控制创建的对象的数量。
关键点:
- 私有构造函数,没有其他类可以实例化一个新对象。
- 私有引用-没有外部修改。
- Public static getInstance方法是唯一可以获取对象的地方。
问:为什么单例模式能确保实例独一无二?
答:因为单例模式没有公开的构造器,构造器是私有的,因此他人无法自己创建实例对象。而且他人想获取实例必须通过调用getInstance静态方法得到实例,实例也许是调用时创建的,也许是之前已经创建好的。
类图

Java经典实现
私有构造器、一个静态方法、一个静态变量。
懒汉Lazy Mode:
public class Singleton{// 使用一个静态变量记录Stingleton的唯一实例private static Singleton uniqueInstance;// 这里是其他有用的实例化变量// 私有构造方法private Singleton(){} public static Singleton getInstance(){if(uniqueInstance == null){uniqueInstance = new Singleton();}return uniqueInstance;}// 其他有用的方法
}
饿汉Eager Mode:
public class Singleton2 {// 使用一个静态私有变量记录Stingleton的唯一实例private static Singleton2 uniqueInstance = new Singleton2();// 这里是其他有用的实例化变量// 私有构造方法private Singleton2(){}public static Singleton2 getInstance(){return uniqueInstance;}// 其他有用的方法
}
在饿汉下的多线程案例
单例类GlobalNum.java
public class GlobalNum {private static GlobalNum gn=new GlobalNum();private int num=0;public static GlobalNum getInstance(){return gn;}public synchronized int getNum() //加锁{return ++num; //返回访问次数}
}
主方法SingleMain.java
class NumThread extends Thread{private String threadName;public NumThread(String name){threadName=name;}public void run(){ GlobalNum gnObj=GlobalNum.getInstance();for (int i = 0; i < 5; i++) {System.out.println(threadName+"第"+gnObj.getNum()+"次访问");try {this.sleep(1000);} catch (Exception e) {// TODO: handle exceptionSystem.out.println("错误");} }}
}public class SingleMain {
//测试单件模式public static void main(String[] args) {// TODO Auto-generated method stubNumThread thread1=new NumThread("线程1");NumThread thread2=new NumThread("线程2");thread1.start();thread2.start();}
}
JDK8运行结果:
线程1第2次访问
线程2第1次访问
线程1第3次访问
线程2第4次访问
线程1第5次访问
线程2第6次访问
线程1第7次访问
线程2第8次访问
线程1第9次访问
线程2第10次访问
在懒汉下的多线程案例
getInstance方法添加synchronized关键字,防止不同线程创建多个实例对象从而违反单例模式。
public class GlobalNum {private static GlobalNum globalNum;private int num=0;// getInstance方法添加synchronized关键字,防止创建多个实例public static synchronized GlobalNum getInstance(){if(globalNum==null){globalNum = new GlobalNum();return globalNum;}return globalNum;}public synchronized int getNum() //加锁{return ++num; //返回访问次数}
}
主方法SingleMain.java
同上
输出结果:
线程1第1次访问
线程2第2次访问
线程1第4次访问
线程2第3次访问
线程1第6次访问
线程2第5次访问
线程1第7次访问
线程2第8次访问
线程1第9次访问
线程2第10次访问
如果上述getInstance不添加synchronized,则会造成输出:
线程1第1次访问
线程2第1次访问
线程1第2次访问
线程2第2次访问
线程1第3次访问
线程2第3次访问
线程1第4次访问
线程2第4次访问
线程1第5次访问
线程2第5次访问
—————————————
上述懒汉下的多线程案例虽然达到预想效果但是存在缺陷:为了防止多个线程创建多个对象,给getInstance添加synchronized,但实际上只有第一次执行getInstance方法,才需要真正的同步,当已经创建好对象时,后续无需在同步getInstance方法(导致后续每次调用getInstance,同步变成累赘,性能资源浪费)。
改进:使用双重检查加锁,减少使用同步。
添加volatile及synchronized同步块
public class GlobalNum {private static volatile GlobalNum globalNum;private int num=0;public static GlobalNum getInstance(){if(globalNum==null){synchronized(GlobalNum.class){if(globalNum==null)globalNum = new GlobalNum();}}return globalNum;}public synchronized int getNum() //加锁{return ++num; //返回访问次数}
}
总结
- 单例模式确保一个程序中的一个类只有一个实例。
- 单例模式提供访问这个实例的全局访问点。
- Java实现单例模式:私有构造器、一个静态变量、一个静态方法。
- 确定性能资源的限制后,在多线程情况下,谨慎选择合适的方法实现单例模式。
参考:
HeadFirst设计模式、https://www.programcreek.com/2011/07/java-design-pattern-singleton/
相关文章:
【设计模式】单例模式Singleton(Java)
文章目录定义类图Java经典实现懒汉Lazy Mode:饿汉Eager Mode:在饿汉下的多线程案例在懒汉下的多线程案例总结定义 单例模式(单件模式)确保一个类只有一个实例,并提供一个全局访问点。——HeadFirst 单例模式通过过防…...
机器学习中的公平性
文章目录机器学习公平性评估指标群体公平性指标个人公平性指标引起机器学习模型不公平的潜在因素提升机器学习模型公平性的措施机器学习公平性 定义: 机器学习公平性主要研究如何通过解决或缓解“不公平”来增加模型的公平性,以及如何确保模型的输出结果…...
Docker镜像之Docker Compose讲解
文章目录1 docker-compose1.1 compose编排工具简介1.2 安装docker-compose1.3 编排启动镜像1.4 haproxy代理后端docker容器1.5 安装socat 直接操作socket控制haproxy1.6 compose中yml 配置指令参考1.6.1 简单命令1.6.2 build1.6.3 depends_on1.6.4 deploy1.6.5 logging1.6.6 ne…...
蓝桥杯30天真题冲刺|题解报告|第三十天
大家好,我是snippet,今天是我们这次蓝桥省赛前一起刷题的最后一天了,今天打了一场力扣周赛,前面3个题都是有思路的,第三个题只过了一半的案例,后面看完大佬们的题解彻悟,下面是我今天的题解 目录…...
配置 Git Husky 代码提交约束
介绍 Git Husky 是一个可以管理 Git Hooks 的工具,它可以帮助我们在代码提交的时候运行脚本,以确保代码提交符合特定的规范和约定。 在 Git 中,允许在操作特定的事件时执行特定的脚本,这些事件我们称之为 Hooks。 Git Husky 利…...
IntelliJ IDEA 2023.1 最新变化
文章目录IntelliJ IDEA 2023.1 最新变化一. 主要更新1. 新 UI 增强 测试版启用新 UI2. 在项目打开时更早提供 IDE 功能3. 更快地导入 Maven 项目4.后台提交检查5. Spring Security 匹配器和请求映射的导航 Ultimate二. 用户体验1. 全 IDE 缩放2. 保存多个工具窗口布局的选项3. …...
stm32学习笔记-9 USART串口
9 USART串口 文章目录9 USART串口9.1 串口通信协议9.2 stm32的片上外设-USART9.3 USART收发相关实验9.3.1 实验1:串口发送9.3.2 实验2:移植printf函数9.3.3 实验3:串口发送接收9.4 USART串口数据包9.5 USART数据包相关实验9.5.1 实验1&#x…...
【蓝桥杯】每日四道编程题(两道真题+两道模拟)| 第四天
专栏: 蓝桥杯——每日四道编程题(两道真题两道模拟) “蓝桥杯就要开始了,这些题刷到就是赚到” ₍ᐢ..ᐢ₎♡ 另一个专栏: 蓝桥杯——每日四道填空题(两道真题两道模拟题) 目录 专栏࿱…...
大家有没有时候觉得,递归,分治,回溯,傻傻分不清楚?
递归,分治,回溯的定义 递归(Recursion) 递归是一种解决问题的方法,它将一个问题分解成一个或多个较小的相同类型的子问题,然后通过递归调用自身来解决这些子问题。递归通常包括一个基本情况(b…...
Java 8 - Lambda 表达式
1. 函数式接口 当一个接口中只有一个非 default 修饰的方法,这个接口就是一个函数式接口用 FunctionalInterface 标注 1)只有一个抽象方法 FunctionalInterface public interface MyInterface {void print(int x); } 2)只有一个抽象方法和…...
【Ruby学习笔记】4.Ruby 类和对象及类案例
前言 本章介绍Ruby的类和对象及类案例。 Ruby 类和对象 Ruby 是一种完美的面向对象编程语言。面向对象编程语言的特性包括: 数据封装数据抽象多态性继承 这些特性将在 面向对象的 Ruby 中进行讨论。 一个面向对象的程序,涉及到的类和对象。类是个别…...
分享一个计算表格内单元格合并的工具,支持行合并、列合并等常见场景
分享一个计算表格内单元格合并的工具,支持行合并、列合并等常见场景 效果图 安装 cj-toolkit-x/table-cell-merger 插件 npm i cj-toolkit-x/table-cell-merger使用方法 import {TableCellMerger} from "cj-toolkit-x/table-cell-merger" // 创建一个单…...
CUDA编程(三):Hello world
CUDA编程(三):Hello worldCUDA编程Hello worldCUDA编程 CUDA是Compute Unified Device Architecture的缩写,由英伟达公司2007年开始推出,初衷是为GPU增加一个易用的编程接口,让开发者无需学习复杂的着色语…...
二十九、String的不可变性
一、String的基本特性 1.String:字符串,使用一对“”引起来表示 1)String s1 “hallo”; //字面量的定义方式 2)String 说 new String(“hello”)’ 2.String声明为final的,不可被继承。 3.String实现了Serialzable接口:表示字符串是支持序列化的。实…...
TCP服务器如何使用select处理多客户连接
TCP是一种面向连接的通信方式,一个TCP服务器难免会遇到同时处理多个用户的连接请求的问题,本文用一个简化的实例说明如何在一个TCP服务器程序中,使用select处理同时出现的多个客户连接,文章给出了程序源代码,本文假定读者已经具备了基本的socket编程知识,熟悉基本的服务器…...
python字符编码
目录 ❤ 前言 文本编辑器存取文件的原理(nodepad,pycharm,word) python解释器执行py文件的原理 ,例如python test.py 总结 ❤ 什么是字符编码? ASCII MBCS Unicode ❤ 字符编码的发展史 阶段一: 现代计算…...
面向对象练习题(8)
目录 第一题 第二题 第三题 第一题 思路分析: 1.Person p new Student();这就是一个向上转型,让父类的引用指向子类的对象,但是向上转型不能访问子类的属性和方法 我们在写代码时看的是编译类型 在运行是看的是运行类型 p.run(); p.eat(); …...
重构类关系-Extract Interface提炼接口八
重构类关系-Extract Interface提炼接口八 1.提炼接口 1.1.使用场景 若干客户使用类接口中的同一子集,或者两个类的接口有部分相同。将相同的子集提炼到一个独立接口中。 类之间彼此互用的方式有若干种。“使用一个类”通常意味用到该类的所有责任区。另一种情况…...
vivo手机各系列简介和拆解
Vivo是中国智能手机制造商,其产品线较多,主要包括以下系列: X系列:X系列是Vivo的高端智能手机系列,注重出色的拍照性能、高质量的音效和高端的设计。该系列主要面向追求高质量拍照和高端体验的用户。 V系列࿱…...
Redis:redis通用命令;redis常见数据结构;redis客户端;redis的序列化
一、redis命令 1.redis通用命令 Redis 通用命令是一些 Redis 下可以作用在常用数据结构上的常用命令和一些基础的命令 常见的命令有: keys 查看符合模板的所有key,不建议在生产环境设备上使用,因为keys会模式匹配所有符合条件的key&#…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用
文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么?1.1.2 感知机的工作原理 1.2 感知机的简单应用:基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...
