单例模式五种实现方式以及在JDK中的体现
单例模式五种实现方式以及在JDK中的体现
一、五种实现方式
1、饿汉式
- 构造私有
- 提供一个静态私有的成员常量,类型就是单例类型,值是用私有构造创造出来的唯一实例
- 提供公共的静态方法获取上述的静态成员常量
public class Singleton1 implements Serializable {
//(1)构造私有
private Singleton1(){
//添加if判断防止单例模式被破坏
if(INSTANCE != null) {
throw new RuntimeException("单例构造器禁止反射调用");
}
System.out.println("private Singleton1()");
}
//(2)提供一个静态私有的成员常量,类型就是单例类型,值是用私有构造创造出来的唯一实例
private static final Singleton1 INSTANCE = new Singleton1();
//(3)提供公共的静态方法获取上述的静态成员常量
public static Singleton1 getInstance() {
return INSTANCE;
}
}
注意:对应所有的单例模式实现方式,如果实现Serializable接口,可能会被反射,反序列化等操作破坏单例,
2、枚举饿汉式
- 枚举类,只定义一个变量
- 构造私有
- 提供公共的静态方法获取枚举常量
public enum Singleton2 {
//(1)枚举类,只定义一个变量
INSTANCE;
//(2)构造私有
private Singleton2(){
System.out.println("private Singleton3()");
}
//(3)获取枚举常量
private static Singleton2 getInstance(){
return INSTANCE;
}
}
3、懒汉式
- 构造私有
- 提供一个静态私有的成员常量,类型就是单例类型,值为空
- 当调用该方法时才new
- 提供公共的静态方法获取上述的静态成员常量
public class Singleton3 {
//(2)声明静态变量为空
private static Singleton3 INSTANCE = null;
//(1)构造私有
private Singleton3(){
System.out.println("private Singleton1()");
}
//(3)提供公共的静态方法获取上述的静态成员变量
//添加synchronized保证在多线程情况下运行正常
public static synchronized Singleton3 getInstance() {
//(4)调用该方法时再new,通过判断是否为空可控制只创建一个实例
if(INSTANCE == null) {
INSTANCE=new Singleton3();
}
return INSTANCE;
}
}
注意:如果在多线程下,要防止多次创建实例,则在静态方法上添加synchronized,但其实我们只要在第一次调用时保证线程安全就可以,因此此方式的效率比较低,如果要提高效率,可以参考下述两种实现方式。
4、DCL懒汉式-双检索懒汉式
DCL懒汉式是为了保证多线程下运行正常,同时提高效率,也就是在静态方法中加锁之前判断是否已经创建了实例。同时静态变量使用volatile修饰
public class Singleton4 {
//(2)声明静态变量为空
private static volatile Singleton4 INSTANCE = null;//可见性,有序性
//(1)构造私有
private Singleton4(){
System.out.println("private Singleton1()");
}
//(3)提供公共的静态方法获取上述的静态成员变量,调用该方法时再new
public static Singleton4 getInstance() {
//在加锁之前进行判断
if(INSTANCE == null) {//一次检索
synchronized (Singleton4.class){
if (INSTANCE == null){//二次检索
INSTANCE=new Singleton4();
}
}
}
return INSTANCE;
}
}
5、懒汉式内部类单例模式
使用内部类的方式可以保证线程安全,建议使用
public class Singleton5 {
//构造私有
private Singleton5(){
System.out.println("private Singleton5()");
}
//创建内部类,在内部类中新建实例
private static class Holder{
static Singleton5 INSTANCE=new Singleton5();
}
private static Singleton5 getInstance(){
return Holder.INSTANCE;
}
}
二、单例模式在jdk中的体现
- Runtime类是单例模式,饿汉式单例实现
- System类中的有一个Console类型的cons变量,采用DCL懒汉式方式实现
- Collections类中有大量单例模式实现,采用内部类懒汉式实现
单例模式五种实现方式以及在JDK中的体现的更多相关文章
- LFU五种实现方式,从简单到复杂
前言 最近刷力扣题,对于我这种 0 基础来说,真的是脑壳疼啊.这个月我估计都是中等和困难题,没有简单题了. 幸好,力扣上有各种大牛给写题解.看着他们行云流水的代码,真的是羡慕不已.让我印象最深刻的就是 ...
- iOS开发中数组常用的五种遍历方式
随着iOS的不断发展,apple也不断推出性能更高的数组遍历方式,下面将对熟悉的五种遍历方式进行列举. 首先定义一个数组,并获取数组长度 NSArray *array=@[",]; NSIn ...
- Spring事务Transaction配置的五种注入方式详解
Spring事务Transaction配置的五种注入方式详解 前段时间对Spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学 ...
- CacheConcurrencyStrategy五种缓存方式
CacheConcurrencyStrategy有五种缓存方式: CacheConcurrencyStrategy.NONE,不适用,默认 CacheConcurrencyStrategy.REA ...
- IPC五种通讯方式
IPC五种通讯方式 1.管道:速度慢,容量有限,只有父子进程能通讯 2.FIFO:任何进程间都能通讯,但速度慢 3.消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题 ...
- CSIC_716_20191129【 单例模式 的五种实现方式】
单例模式 单例模式:在确定类中的属性和方法不变时,需要反复调用该类的情况. 让所有通过该类实例化出的对象,都指向同一个内存地址. 优点:节省内存空间. 单例模式有五种表现形式: 1.通过class ...
- JS 跨域问题常见的五种解决方式
一.什么是跨域? 要理解跨域问题,就先理解好概念.跨域问题是由于javascript语言安全限制中的同源策略造成的. 简单来说,同源策略是指一段脚本只能读取来自同一来源的窗口和文档的属性,这里的同一来 ...
- Java单例模式几种实现方式
在平时的工作.学员的学习以及面试过程中,单例模式作为一种常用的设计模式,会经常被面试官问到,甚至笔试会要求学员现场默写,下面将会就单例模式的实现思路和几种常见的实现方式进行简单的分享. 单例模式,是一 ...
- Flex页面跳转的五种实现方式
Flex页面跳转有很多值得学习的地方,本文向大家介绍一下Flex页面跳转的几种方式,主要包括五种方式,这里为大家一一介绍. AD: 在学习Flex的过程中,你可能会遇到Flex页面跳转的概念,这里 ...
- JavaScript五种继承方式详解
本文抄袭仅供学习http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html 一. 构造函数绑定 ...
随机推荐
- 【TouchGFX】使用CubeMX创建touchgfx项目 -- 初始篇
1.系统构成,黑色块表示组件非必须 2.环境准备 CubeMX:6.0.1 touchgfx:4.15.0 rt-thread:2020-8-14 commit Keil:5.30 board:stm ...
- linux环境C语言实现:h264与pcm封装成AVI格式
前言 拖了很久的AVI音视频封装实例,花了一天时间终于调完了,兼容性不是太好,但作为参考学习使用应该没有问题. RIFF和AVI以及WAV格式,可以参考前面的一些文章.这里详细介绍将一个H264视 ...
- 给Hexo博客文章加密
有的时候博客内容会有变动,首发博客是最新的,其他博客地址可能会未同步,认准https://blog.zysicyj.top 首发博客地址 原文地址 这是个啥 首先, 这是 Hexo 生态圈中 最好的 ...
- [转帖]如何不耍流氓的做运维之-SHELL脚本
https://www.cnblogs.com/luoahong/articles/8504691.html 前言 大家都是文明人,尤其是做运维的,那叫一个斯文啊.怎么能耍流氓呢?赶紧看看,编写SHE ...
- [转帖]通过拓扑 label 进行副本调度
https://docs.pingcap.com/zh/tidb/stable/schedule-replicas-by-topology-labels#%E5%9F%BA%E4%BA%8E%E6%8 ...
- 通过dotnet-dump分析生产环境docker容器部署的应用问题
首先找到对应的docker id并exec进去,然后执行命令并更新apt包+下载procps和wget用于等下拉取dotnet-dump和查看线程 sed -i -e "s@deb.debi ...
- 华为云DTSE携手“灵康宜”构造一站式智慧健康检测云平台
本文分享自华为云社区<华为云DTSE携手"灵康宜"构造一站式智慧健康检测云平台>,作者: HuaweiCloudDeveloper. 打破传统健康监测方式桎梏--非接触 ...
- 官宣!Python 开发者大会(PyCon US)提供在线订阅啦!
今年一开年,我们就遇到了一个天大的"黑天鹅"事件,如今它已蔓延成为了一个全球性事件,而且似乎还要持续一段挺长的时间. 各行各业的人们都受到了牵连,各种计划和安排也要被迫作出调整.今 ...
- SqlSugar跨库查询/多库查询
一.跨库方式1:跨库导航 (5.1.3.24) 优点1:支持跨服务器,支持跨数据库品种, 支持任何类型数据库 优点2: 超级强大的性能,能达到本库联表性能 缺点:不支持子表过滤主表 (方案有ToL ...
- 强化学习从基础到进阶-案例与实践[5.1]:Policy Gradient策略梯度-Cart pole游戏展示
强化学习从基础到进阶-案例与实践[5.1]:Policy Gradient策略梯度-Cart pole游戏展示 强化学习(Reinforcement learning,简称RL)是机器学习中的一个领域 ...