单例模式的七种写法
为什么使用单例?
避免重复创建对象,节省内存,方便管理;一般我们在工具类中频繁使用单例模式;
1.饿汉式(静态常量)-[可用]
/*** 饿汉式(静态常量)*/
public class Singleton1 {private static final Singleton1 INSTANCE = new Singleton1();private Singleton1(){}public static Singleton1 getInstance(){return INSTANCE;}
}
2.饿汉式(静态代码块)[可用]
/*** 饿汉式(静态代码块)*/
public class Singleton2 {private static final Singleton2 INSTANCE;static {INSTANCE = new Singleton2();}private Singleton2(){}public static Singleton2 getInstance(){return INSTANCE;}
}
3.懒汉式(同步方法)[不推荐]
/*** 懒汉式(同步方法)* 不推荐:效率太低了*/
public class Singleton3 {private static Singleton3 instance;private Singleton3(){}public synchronized static Singleton3 getInstance(){if(instance == null){instance = new Singleton3();}return instance;}
}
4.双重检查(有空指针问题)[面试用]
/*** 双重检查-推荐面试使用*/
public class Singleton4 {private static Singleton4 instance;private Singleton4(){}public static Singleton4 getInstance(){if(instance == null){ // 检查一synchronized (Singleton4.class){if(instance == null){ // 检查二instance = new Singleton4();}}}return instance;}
}
双重检查优点:
线程安全,延迟加载,效率较高;
5.双重检查进阶版(volatile)[推荐]
使用volatile目的在于,禁止创建对象时的3个步骤发生重排序,防止创建出的对象空指针问题;
/*** 双重检查 + volatile(禁止创建对象时3个步骤执行流程重排序,防止创建出的对象空指针问题)*/
public class Singleton5 {// 加上volatile防止新建对象时重排序带来的“空指针”问题private volatile static Singleton5 instance;private Singleton5(){}public static Singleton5 getInstance(){if(instance == null){ // 检查一synchronized (Singleton5.class){/*** 为什么使用volatile修饰instance?* 1.新建对象操作不是原子性操作,其由三个操作构成(instance = new Singleton5(););* 1.1.创建一个空的instance;* 1.2.调用构造方法;* 1.3.将创建好的对象赋值给instance实例;* 2.因为创建对象操作不是原子性操作,所以使用volatile来禁止创建对象时重排序* 3.如果不使用volatile修饰instance实例,则创建对象时被JVM重排序后的执行流程可能如下(即出现“空指针问题”)* 1.2 -> 1.1 -> 1.3*/if(instance == null){ // 检查二instance = new Singleton5();}}}return instance;}
}
6.静态内部类[推荐]
* 静态内部类(可用)* 原理:* 外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE故不占内存。* 只有当getInstance()方法第一次被调用时才会去初始化INSTANCE,第一次调用getInstance()方法才会使虚拟机加载SingletonInstance类(实现懒加载)* 因为SingletonInstance类中INSTANCE实例是被static final修饰所以只会被初始化一次,后续调用会直接返回实例不需要进行同步操作;*/
public class Singleton6 {private Singleton6(){}private static class SingletonInstance{private static final Singleton6 INSTANCE = new Singleton6();}public static Singleton6 getInstance(){return SingletonInstance.INSTANCE;}
}
7.枚举[推荐(开发中使用最好)]
/*** 枚举*/
public enum Singleton7 {INSTANCE;public void todoSomething(){System.out.println("我是枚举实现单例模式中的一个普通业务方法...");}// 调用public static void main(String[] args) {Singleton7.INSTANCE.todoSomething();}
}
8.单例模式面试题
8.1.饿汉式的缺点?
没有实现懒加载,容易造成资源的浪费;
8.2.懒汉式的缺点?
为保证线程安全使用同步方法效率低;
8.3.为什么使用“双重检查”不用就不安全吗?
“双重检查”代码中只做第一次检查是线程不安全的;容易创建多个对象。若不用双重检查也可以使用synchronized去修饰获取实例方法来保证线程安全(类似于懒汉式的同步方法);
8.4.双重检查为什么要使用volatile?
1.新建对象操作不是原子性操作,其由三个操作构成(比如:instance = new Singleton5(););
1.1.创建一个空的instance;
1.2.调用构造方法;
1.3.将创建好的对象赋值给instance实例;
2.因为创建对象操作不是原子性操作,所以使用volatile来禁止创建对象时JVM重排序问题;
3.如果不使用volatile修饰instance实例,则创建对象时被JVM重排序后的执行流程可能如下(“空指针问题”),若创建出来的对象为null,由于“可见性”问题,下次去获取实例时还是会创建多个对象;
JVM重排序后执行流程可能为:(即出现空指针问题)
1.2 -> 1.1 -> 1.3
8.5.在生产中用哪种单例的实现方案最好?
使用枚举的方式实现单例最好;
1.写法简单;
2.线程安全;
原因:枚举类会被JVM编译成final修饰的class其继承了枚举这个父类,在父类中各个实例都是
使用static定义的,所以枚举的本质就是一个静态编译的对象;
3.懒加载;
4.防止反序列化重新创建对象;
相关文章:
单例模式的七种写法
为什么使用单例? 避免重复创建对象,节省内存,方便管理;一般我们在工具类中频繁使用单例模式; 1.饿汉式(静态常量)-[可用] /*** 饿汉式(静态常量)*/ public class Singleton1 {private static final Singleton1 INSTANCE new Singleton1();private Singleton1(){}…...

ElasticSearch入门介绍和实战
目录 1.ElasticSearch简介 1.1 ElasticSearch(简称ES) 1.2 ElasticSearch与Lucene的关系 1.3 哪些公司在使用Elasticsearch 1.4 ES vs Solr比较 1.4.1 ES vs Solr 检索速度 2. Lucene全文检索框架 2.1 什么是全文检索 2.2 分词原理之倒排索引…...

【FPGA】分享一些FPGA视频图像处理相关的书籍
在做FPGA工程师的这些年,买过好多书,也看过好多书,分享一下。 后续会慢慢的补充书评。 【FPGA】分享一些FPGA入门学习的书籍【FPGA】分享一些FPGA协同MATLAB开发的书籍 【FPGA】分享一些FPGA视频图像处理相关的书籍 【FPGA】分享一些FPGA高速…...
AUTOSAR从入门到精通-车载以太网(四)
目录 前言 原理 车载以太网发展历史 为何选择车载以太网...

MySQL报错:1054 - Unknown column ‘xx‘ in ‘field list的解决方法
我在操作MySQL遇到1054报错,报错内容:1054 - Unknown column Cindy in field list,下面演示解决方法,非常简单。 根据箭头指示,Cindy对应的应该是VARCHAR文本数字类型,字符串要用引号,所以解决方…...
【Android 13】使用Android Studio调试系统应用之Settings移植(四):40+个依赖子模块之ActionBarShadow
文章目录 一、篇头二、系列文章2.1 Android 13 系列文章2.2 Android 9 系列文章2.3 Android 11 系列文章三、子模块AS移植3.1 AS创建目标3.2 创建ActionBarShadow(1)使用VS Code打开org_settings/SettingsLib目录(2)ActionBarShadow的Manifest.xml(3)ActionBarShadow的An…...

nosql-redis整合测试
nosql-redis整合测试 1、创建项目并导入redis2、配置redis3、写测试类4、在redis中创建key5、访问80826、在集成测试中测试方法 1、创建项目并导入redis 2、配置redis 3、写测试类 4、在redis中创建key 5、访问8082 6、在集成测试中测试方法 package com.example.boot3.redis;…...

智能化中的控制与自动化中的控制不同
智能化中的控制相对于自动化中的控制更加灵活、智能、综合和学习能力强。智能化控制系统能够根据实际情况进行自主决策和优化,适用范围更广,效果更好。 首先,智能化控制系统能够根据外部环境的变化和实时数据的反馈来自主调整和优化控制策略&…...

java练习题之多态练习
1:关于多态描述错误的是(D) A. 父类型的引用指向不同的子类对象 B. 用引用调用方法,只能调用引用中声明的方法 C. 如果子类覆盖了父类中方法,则调用子类覆盖后的方法 D. 子类对象类型会随着引用类型的改变而改变 2:class Supe…...

[原创][R语言]股票分析实战[4]:周级别涨幅趋势的相关性
[简介] 常用网名: 猪头三 出生日期: 1981.XX.XX QQ联系: 643439947 个人网站: 80x86汇编小站 https://www.x86asm.org 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、D…...

esp32使用lvgl,给图片取模显示图片
使用LVGL官方工具。 https://lvgl.io/tools/imageconverter 上传图片,如果想要透明效果,那么选择 输出格式C array,点击Convert进行转换。 下载.c文件放置到工程下使用即可。...
R语言使用scitb包10分钟快速绘制论文基线表
scitb包目前进行了升级到1.7版本了,我做了一个操作视频,如何快速绘制基线表。 scitb包绘制基线表 可以配套看下我的关于scitb包文章理解一下 scitb包1.6版本发布,一个为制作专业统计表格而生的R包...

类和对象
1 类定义: class ChecksumAccumulator {// class definition goes here } 你就能创建 ChecksumAccumulator 对象:new CheckSumAccumulator 注:1scala类中成员默认是public类型,若设为私有属性则必须加private关键字。在scala中是…...

Py之tensorflow-addons:tensorflow-addons的简介、安装、使用方法之详细攻略
Py之tensorflow-addons:tensorflow-addons的简介、安装、使用方法之详细攻略 目录 tensorflow-addons的简介 tensorflow-addons的安装 tensorflow-addons的使用方法 1、使用 TensorFlow Addons 中的功能: tensorflow-addons的简介 TensorFlow Addon…...

STM32G4x FLASH 读写配置结构体(LL库下使用)
主要工作就是把HAL的超时用LL库延时替代,保留了中断擦写模式、轮询等待擦写,我已经验证了部分。 笔者用的芯片为STM32G473CBT6 128KB Flash,开环环境为CUBEMXMDK5.32,因为G4已经没有标准库了,笔者还是习惯使用标准库的…...

【AI提示词人物篇】创新艺术未来,让科技改变想象空间
AI 绘画学习难度和练习技巧 学习绘画的技巧 学习能难度: 外貌特征:AI需要学习识别和理解各种外貌特征,如发型、肤色、眼睛颜色等。这可能需要大量的训练数据和复杂的模型架构。 镜头提示:AI需要学习理解不同镜头提示的含义&…...
登录shell与非登录shell、交互式与非交互式shell的知识点详细总结
一、登录shell与非登录shell 1.登录shell定义:指的是当用户登录系统时所取的那个shell,登录shell属于交互式shell。 登陆shell通常指的是:用户通过输入用户名/密码(或证书认证)后启动的shell.例如: 当时…...

【教学类-42-02】20231224 X-Y 之间加法题判断题2.0(按2:8比例抽取正确题和错误题)
作品展示: 0-5: 21题,正确21题,错误21题42题 。小于44格子,都写上,哪怕输入2:8,实际也是5:5 0-10 66题,正确66题,错误66题132题 大于44格子,正确66题抽取44*…...

轻量Http客户端工具VSCode和IDEA
文章目录 前言Visual Studio Code 的插件 REST Client编写第一个案例进阶,设置变量进阶,设置Token IntelliJ IDEA 的 HTTP请求构建http脚本HTTP的环境配置结果值暂存 前言 作为一个WEB工程师,在日常的使用过程中,HTTP请求是必不可…...

机器学习或深度学习的数据读取工作(大数据处理)
机器学习或深度学习的数据读取工作(大数据处理)主要是.split和re.findall和glob.glob运用。 读取文件的路径(为了获得文件内容)和提取文件路径中感兴趣的东西(标签) 1,“glob.glob”用于读取文件路径 2,“.…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)
这是系统中断服务程序的默认处理汇编函数,如果我们没有定义实现某个中断函数,那么当stm32产生了该中断时,就会默认跑这里来了,所以我们打开了什么中断,一定要记得实现对应的系统中断函数,否则会进来一直循环…...