当前位置: 首页 > news >正文

Java面试之单例模式的六种实现方式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、为什么要用单例模式
  • 二、单例模式的六种实现
    • 2.1 饿汉式
      • 2.1.1 饿汉式代码实现
      • 2.1.2 饿汉式代码实现要点解析
      • 2.1.3 饿汉式代码实现优点
      • 2.1.4 饿汉式代码实现缺点
    • 2.2 懒汉式1.0
      • 2.2.1 懒汉式1.0代码实现
      • 2.2.2 懒汉式1.0代码实现要点解析
      • 2.2.3 懒汉式1.0代码实现优点
      • 2.2.4 懒汉式1.0代码实现缺点
    • 2.3 懒汉式2.0
      • 2.3.1 懒汉式2.0代码实现
      • 2.3.2 懒汉式2.0代码实现要点解析
      • 2.3.3 懒汉式2.0代码实现优点
      • 2.3.4 懒汉式2.0代码实现缺点
    • 2.4 懒汉式3.0——双重检查Double Check
      • 2.4.1 双重检查代码实现
      • 2.4.2 双重检查代码实现要点解析
      • 2.4.3 双重检查代码实现优点
      • 2.4.4 双重检查代码实现缺点
    • 2.5 静态内部类(推荐)
      • 2.5.1 静态内部类代码实现
      • 2.5.2 静态内部类代码实现要点解析
      • 2.5.3 静态内部类代码实现优点
      • 2.5.4 静态内部类代码实现缺点
      • 2.5.5 静态内部类与饿汉式对比
    • 2.6 枚举(推荐)
      • 2.6.1 枚举代码实现
      • 2.6.2 枚举代码实现要点解析
      • 2.6.3 枚举实现优点


前言

由于设计模式在面向对象中起着举足轻重的作用,在面试中很多公司都喜欢问一下有关设计模式的问题。在常用的设计模式中,Singleton单例模式是唯一一个能用短短几十行代码完整实现的模式,因此,写一个Singletion类型是一个很常见的面试题。


一、为什么要用单例模式

节省内存,单例对象可避免频繁的创建与销毁,带来性能的提升。
在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。

二、单例模式的六种实现

2.1 饿汉式

2.1.1 饿汉式代码实现

public class Singleton{private Singleton(){}private static Singleton instance = new Singleton();public static Singleton getInstance(){return instance;}
}

2.1.2 饿汉式代码实现要点解析

1、私有构造
2、创建私有静态实例
3、提供公有静态get方法返回该静态实例

2.1.3 饿汉式代码实现优点

1、实现简单
2、无线程安全问题

2.1.4 饿汉式代码实现缺点

1、初始化耗时,导致系统启动缓慢
2、在类装载的时候就完成了实例化,没有做到Lazy Loading(延迟加载)、按需加载
3、极端情况下,还是可以拿到多实例,如通过反射。

2.2 懒汉式1.0

2.2.1 懒汉式1.0代码实现

public class Singleton{private Singleton(){}private static Singleton instance = null;public static Singleton getInstance(){if(instance == null){instance = new Singleton();}return instance;}
}

2.2.2 懒汉式1.0代码实现要点解析

1、私有构造
2、初始化一个为null的静态实例instance
3、提供公有静态get方法,判断instance为null时,则创建该对象并赋给instance,然后返回该静态实例

2.2.3 懒汉式1.0代码实现优点

1、延迟加载,在使用时才会开辟空间

2.2.4 懒汉式1.0代码实现缺点

1、线程不安全,只能在单线程情况下使用,在多线程情况下,一个线程进if(instance == null)判断中,还未来得及创建对象,另外一个线程也来到判断语句,这时也会通过判断,这样就会创建多个实例。

总的来说在多线程环境中不能使用这种方式。

2.3 懒汉式2.0

2.3.1 懒汉式2.0代码实现

public class Singleton{private Singleton(){}private static Singleton instance = null;public static synchronized Singleton getInstance(){if(instance == null){instance = new Singleton();}return instance;}
}

2.3.2 懒汉式2.0代码实现要点解析

1、私有构造
2、创建私有静态实例
3、提供加synchronized的公有静态get方法返回该静态实例

2.3.3 懒汉式2.0代码实现优点

1、用的时候开辟内存
2、解决线程安全问题

2.3.4 懒汉式2.0代码实现缺点

1、效率太低。下一个线程想要获取对象,必须等待上一个线程释放锁之后才能获取。每次调用都需要获取锁与释放锁,在大量并发请求时将产生性能问题。
2、并发度低。由于加入了synchronized,并行度为1,导致并发度低。
3、极端情况下,还是可以拿到多实例,如通过反射。

2.4 懒汉式3.0——双重检查Double Check

2.4.1 双重检查代码实现

public class Singleton{private Singleton(){}private static Singleton instance = null;public static synchronized Singleton getInstance(){if(instance == null){//这个检查是提高效率的synchronized (Singleton.class){if(instance == null){//这个检查是保证线程安全的instance = new Singleton();}}}return instance;}
}

2.4.2 双重检查代码实现要点解析

1、私有构造
2、创建私有静态实例
3、提供加synchronized的公有静态get方法返回该静态实例,该get方法中首先判断instance是否为null,然后加个synchronized块,里面再对instance进行判断,为空才创建对象

2.4.3 双重检查代码实现优点

1、实现简单
2、立即加载,无线程安全问题

2.4.4 双重检查代码实现缺点

极端情况下,还是可以拿到多实例,如通过反射。

2.5 静态内部类(推荐)

2.5.1 静态内部类代码实现

public class Singleton{private Singleton(){}private static Singleton SingletonInstance {private static final Singleton INSTANCE = new Singleton();}public static Singleton getInstance(){return SingletonInstance.INSTANCE;}
}

2.5.2 静态内部类代码实现要点解析

1、私有构造
2、创建私有静态内部类,该静态内部类中含有static 和final修饰的实例对象
3、提供公有静态get方法返回该静态实例

2.5.3 静态内部类代码实现优点

1、延迟加载,效率高
2、无线程安全问题。类的静态属性只会在第一次加载类时初始化,这样JVM帮助我们保证了线程安全性,因为在类初始化时别的线程无法进入。

2.5.4 静态内部类代码实现缺点

静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。
极端情况下,还是可以拿到多实例,如通过反射。

2.5.5 静态内部类与饿汉式对比

此方法可以看作饿汉式的改进版,两者都采用类装载机制来保证初始化实例时只有一个线程。
不同之处在于饿汉式只要Singleton类被装载就会实例化,没有延迟加载;
而静态内部类方式再Singleton类被装载时并不会立即实例化,而是在需要实例化时才会调用getInstance方法装载SingletonInstance 类,从而完成Singleton实例化。

总的来说推荐使用。

2.6 枚举(推荐)

2.6.1 枚举代码实现

public class Singleton{//内部类使用枚举类private enum SingletonEnum {INSTANCE;private Singleton singleton;//在枚举类的构造器里初始化singletonSingletonEnum() {singleton = new Singleton ();}private Singleton getSingleton() {return singleton;}}//对外提供获取单例的方法public static Singleton getInstance(){return SingletonEnum.INSTANCE.getSingleton();}
}

2.6.2 枚举代码实现要点解析

1、内部类使用枚举类
2、在枚举类的构造器里初始化singleton,提供私有方法供本类获取singleton
3、对外提供获取单例的方法

2.6.3 枚举实现优点

1、支持延迟加载,可做到按需加载
2、支持高并发
3、防止反射和反序列化攻击

总的来说推荐使用。


相关文章:

Java面试之单例模式的六种实现方式

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、为什么要用单例模式二、单例模式的六种实现2.1 饿汉式2.1.1 饿汉式代码实现2.1.2 饿汉式代码实现要点解析2.1.3 饿汉式代码实现优点2.1.4 饿汉式代码实现缺…...

re正则入门

🌸re正则入门 正则表达式 (Regular Expression) 又称 RegEx, 是用来匹配字符的一种工具. 在一大串字符中寻找你需要的内容. 它常被用在很多方面, 比如网页爬虫, 文稿整理, 数据筛选等等 简单的匹配 正则表达式无非就是在做这么一回事. 在文字中找到特定的内容, 比如…...

C++ Day5

目录 一、静态成员 1.1 概念 1.2 格式 1.3 银行账户实例 二、类的继承 2.1 目的 2.2 概念 2.3 格式 2.4 继承方式 2.5 继承中的特殊成员函数 2.5.1 构造函数 2.5.2析构函数 2.5.3 拷贝构造函数 2.5.4拷贝赋值函数 总结: 三、多继承 3.1 概念 3.2 格…...

el-element:自定义参数

希望在下拉框、输入框、多选框中添加自定义参数,这在项目中是非常常见的 1、 Select选择器中remote-method方法带自定义参数 :remote-method"(query)>{remoteMethod(query,自定义参数)}" remoteMethod(query, pid){ } 2、 el多选框方法追加参数&…...

“分布式”与“集群”初学者的技术总结

一、“分布式”与“集群”的解释: 分布式:把一个囊肿的系统分成无数个单独可运行的功能模块 集群: 把相同的项目复制进行多次部署(可以是一台服务器多次部署,例如使用8080部署一个,8081部署一个&#xff0c…...

C++day5(静态成员、类的继承、多继承)

一、Xmind整理&#xff1a; 二、上课笔记整理&#xff1a; 1.静态数据成员静态成员函数&#xff08;银行账户实例&#xff09; #include <iostream>using namespace std;class BankAccount { private:double balance; //余额static double interest_rate; //利率 p…...

2023MySQL+MyBatis知识点整理

文章目录 主键 外键 的区别&#xff1f;什么是范式&#xff1f;什么是反范式&#xff1f;什么是事务&#xff1f;MySQL事务隔离级别&#xff1f;MySQL事务默认提交模式&#xff1f;MySQL中int(1)和int(10)的区别MySQL 浮点数会丢失精度吗&#xff1f;MySQL支持哪几种时间类型&a…...

【随笔】如何使用阿里云的OSS保存基础的服务器环境

使用阿里云OSS创建一个存储仓库&#xff1a;bucket 在Linux上下载并安装阿里云的ossutil工具 // 命令行&#xff0c;是linux环境 3. 安装ossutil。sudo -v ; curl https://gosspublic.alicdn.com/ossutil/install.sh | sudo bash 说明:安装过程中&#xff0c;需要使用解压工具…...

汽车电子笔记之:AUTOSA架构下的多核OS操作系统

目录 1、AUTOSAR多核操作系统 1.1、OS Application 1.2、多核OS的软件分区 1.3、任务调度 1.4、核间任务同步 1.5、计数器、报警器、调度表 1.6、自旋锁与共享资源 1.7、核间通信IOC 1.8、OS Object中元素交互 1.9、多核OS的启动与关闭 2、多核OS注意事项 2.1、最小…...

解决华为云ping不通的问题

进入华为云控制台。依次选择&#xff1a;云服务器->点击服务器id->安全组->更改安全组->添加入方向规则&#xff0c;添加一个安全组规则&#xff08;ICMP&#xff09;&#xff0c;详见下图 再次ping公网ip就可以ping通了 产生这一问题的原因是ping的协议基于ICMP协…...

数据结构入门 — 链表详解_双向链表

前言 数据结构入门 — 双向链表详解* 博客主页链接&#xff1a;https://blog.csdn.net/m0_74014525 关注博主&#xff0c;后期持续更新系列文章 文章末尾有源码 *****感谢观看&#xff0c;希望对你有所帮助***** 系列文章 第一篇&#xff1a;数据结构入门 — 链表详解_单链表…...

时序预测 | MATLAB实现PSO-KELM粒子群算法优化核极限学习机时间序列预测(含KELM、ELM等对比)

时序预测 | MATLAB实现PSO-KELM粒子群算法优化核极限学习机时间序列预测&#xff08;含KELM、ELM等对比&#xff09; 目录 时序预测 | MATLAB实现PSO-KELM粒子群算法优化核极限学习机时间序列预测&#xff08;含KELM、ELM等对比&#xff09;预测效果基本介绍模型介绍程序设计参…...

SSL/TLS协议的概念、工作原理、作用以及注意事项

个人主页&#xff1a;insist--个人主页​​​​​​ 本文专栏&#xff1a;网络基础——带你走进网络世界 本专栏会持续更新网络基础知识&#xff0c;希望大家多多支持&#xff0c;让我们一起探索这个神奇而广阔的网络世界。 目录 一、SSL/TLS协议的基本概念 二、SSL/TLS的工作…...

[Stable Diffusion教程] 第一课 原理解析+配置需求+应用安装+基本步骤

第一课 原理解析配置需求应用安装基本步骤 本次内容记录来源于B站的一个视频 以下是自己安装过程中整理的问题及解决方法&#xff1a; 问题&#xff1a;stable-diffusion-webui启动No Python at ‘C:\xxx\xxx\python.exe‘ 解答&#xff1a;打开webui.bat 把 if not de…...

uniapp结合Canvas+renderjs根据经纬度绘制轨迹(二)

uniapp结合Canvasrenderjs根据经纬度绘制轨迹 文章目录 uniapp结合Canvasrenderjs根据经纬度绘制轨迹效果图templaterenderjsjs数据结构 ​ 根据官方建议要想在 app-vue 流畅使用 Canvas 动画&#xff0c;需要使用 renderjs 技术&#xff0c;把操作canvas的js逻辑放到视图层运…...

VR全景加盟会遇到哪些问题?全景平台会提供什么?

想创业&#xff0c;你是否也遇到这些问题呢&#xff1f;我是外行怎么办&#xff1f;没有团队怎么办&#xff1f;项目回本周期快吗&#xff1f;项目靠谱吗&#xff1f;加盟平台可信吗&#xff1f;等等这类疑问。近几年&#xff0c;VR产业发展迅速&#xff0c;尤其是VR全景项目在…...

如何进行微服务的集成测试

集成测试的概念 说到集成测试&#xff0c;相信每个测试工程师并不陌生&#xff0c;它不是一个崭新的概念&#xff0c;通过维基百科定义可以知道它在传统软件测试中的含义。 Integration testing (sometimes called integration and testing, abbreviated I&T) is the pha…...

spark grpc 在master运行报错 exitcode13 User did not initialize spark context

程序使用sparksql 以及protobuf grpc &#xff0c;执行报错 ApplicationMaster: Final app status: FAILED, exitCode: 13, (reason: Uncaught exception: java.lang.IllegalStateException: User did not initialize spark context! 先说原因 &#xff1a; 1.使用了不具备权限…...

nginx 反向代理的原理

Nginx&#xff08;发音为"engine X"&#xff09;是一个高性能、轻量级的开源Web服务器和反向代理服务器。它的反向代理功能允许将客户端的请求转发到后端服务器&#xff0c;然后将后端服务器的响应返回给客户端。下面是Nginx反向代理的工作原理&#xff1a; 1.客户端…...

【SpringBoot】第二篇:RocketMq使用

背景&#xff1a; 本文会介绍多种案例&#xff0c;教大家如何使用rocketmq。 一般rocketmq使用在微服务项目中&#xff0c;属于分模块使用。这里使用springboot单体项目来模拟使用。 本文以windows系统来做案例。 下载rocketmq和启动&#xff1a; RocketMQ 在 windows 上运行…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)

可以使用Sqliteviz这个网站免费编写sql语句&#xff0c;它能够让用户直接在浏览器内练习SQL的语法&#xff0c;不需要安装任何软件。 链接如下&#xff1a; sqliteviz 注意&#xff1a; 在转写SQL语法时&#xff0c;关键字之间有一个特定的顺序&#xff0c;这个顺序会影响到…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器

一、原理介绍 传统滑模观测器采用如下结构&#xff1a; 传统SMO中LPF会带来相位延迟和幅值衰减&#xff0c;并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF)&#xff0c;可以去除高次谐波&#xff0c;并且不用相位补偿就可以获得一个误差较小的转子位…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归&#xff08;Tail Recursion&#xff09; 什么是 Loop&#xff08;循环&#xff09;&#xff1f; 复杂度分析 头递归&#xff08;Head Recursion&#xff09; 树形递归&#xff08;Tree Recursion&#xff09; 线性递归&#xff08;Linear Recursion&#xff09;…...

Vue 3 + WebSocket 实战:公司通知实时推送功能详解

&#x1f4e2; Vue 3 WebSocket 实战&#xff1a;公司通知实时推送功能详解 &#x1f4cc; 收藏 点赞 关注&#xff0c;项目中要用到推送功能时就不怕找不到了&#xff01; 实时通知是企业系统中常见的功能&#xff0c;比如&#xff1a;管理员发布通知后&#xff0c;所有用户…...