设计模式——单例模式详解
单例
介绍
单例模式(Singleton Pattern)是Java中最基础最简单的设计模式之一,这种模式属于创建型模式
,提供的就是一种创建对象的方式。这种模式中的单一类创建自己的对象,确保只有一个对象被创建,并且为所有对象提供一个访问它的全局访问点。
单例模式用来解决频繁创建与销毁实例对象问题,当我们想要控制实例创建个数或者复用实例时,就可以使用单例模式,这样有助于节省系统资源。
特点
- 单例类,顾名思义,只有一个实例。
- 单例类必须是自己创建自己的唯一实例。
- 单例类必须给所有对象提供这个唯一实例。
- 构造函数私有。
应用场景
适用范围
- 频繁的访问数据库或文件的对象。
- 频繁的需要实例化,然后销毁的对象。
- 创建对象耗时长且耗资源,但是又需要常用的对象。
使用举例
- Windows的任务管理器,每次只能打开一个。
- 应用程序的日志应用。
- 网上在线人数统计。
- 配置文件的访问类。
- 数据库的连接池。
- 多线程的线程池。
- 操作系统的文件系统。
设计思路
- 一个类每次都返回唯一的对象(每次返回都是同一个对象实例)。
- 提供一个获取该实例的方法。(基本上都是静态方法)
- 构造函数私有。
加载分类
提前加载
:在应用开始时就创建单例实例。延迟加载
:在getInstance()方法
首次被调用时才调用单例创建,即需要使用时,才加载创建单例对象实例。
单例分类
1 饿汉式单例
介绍
- 类加载时就初始化好实例对象,容易产生垃圾对象,浪费内存。
- 无锁,执行效率高。
- 天生线程安全,因为类加载时就已初始化好实例。
代码
/*** 饿汉式单例* @author Andya* @date 2021/3/9*/
public class EHanSingleInstance {//饿汉式:初始化时就建好实例private static final EHanSingleInstance instance = new EHanSingleInstance();private EHanSingleInstance() {doSomething();}public static EHanSingleInstance getInstance() {return instance;}public void doSomething() {}
}
2 懒汉式单例
介绍
- 饿汉式属于延迟加载初始化。
- 若不加锁,则为非线程安全的。
- 若加锁,则为线程安全的,但效率很低,基本上每次都要同步。
无锁懒汉式代码
/*** 无锁懒汉式单例,非线程安全* @author Andya* @date 2021/3/9*/
public class LanHanNoLockSingleInstance {//懒汉式:初始化时不创建实例,等需要时再创建private static LanHanNoLockSingleInstance instance;private LanHanNoLockSingleInstance() {doSomething();}public static LanHanNoLockSingleInstance getInstance() {//先判断是否为空,若为空创建一个新的实例if (instance == null) {instance = new LanHanNoLockSingleInstance();}return instance;}public void doSomething() {}
}
加锁懒汉式代码
/*** 加锁懒汉式单例,线程安全* @author Andya* @date 2021/3/9*/
public class LanHanWithLockSingleInstance {//懒汉式:初始化时不创建实例,等需要时再创建private static LanHanWithLockSingleInstance instance;private LanHanWithLockSingleInstance() {doSomething();}public static synchronized LanHanWithLockSingleInstance getInstance() {//先判断是否为空,若为空创建一个新的实例if (instance == null) {instance = new LanHanWithLockSingleInstance();}return instance;}public void doSomething() {}
}
3 双重检锁式单例
介绍
在多线程应用中使用这种模式可以保证线程安全。因为如果实例为空,有可能存在两个线程同时调用getInstance()
方法的情况,这样的话,第一个线程会首先使用新构造器实例化一个单例对象,但此时它还没有完成单例对象的实例化操作,同时第二个线程也检查到单例实例为空,也会开始实例化单例对象,这就造成了2次实例化对象。所以多线程应用中,需要锁
来检查实例是否线程安全。
- 静态方法锁
public static synchronized Singleton getInstance()
- 代码块锁
synchronized(SingleInstance.class){if (instance == null) {instance = new SingleInstance();}
}
虽然加锁可以保证线程安全,但是会带来延迟,因为加锁后,代码块在同一时刻只能被一个线程执行,但是同步锁只有在实例没被创建的时候才会起作用。如果单例实例已经被创建,其实不需要走该步骤。因此,我们可以在代码块锁外面再加一层实例空判断。instance == null
被检查2
次。
if (instance == null) {synchronized(SingleInstance.class){if (instance == null) {instance = new SingleInstance();}}
}
代码
/*** 双检锁单例* @author Andya* @date 2021/3/9*/
public class DoubleCheckSingleInstance {//使用volatile保证多线程的可见性private static volatile DoubleCheckSingleInstance instance;private DoubleCheckSingleInstance() {doSomething();}public static DoubleCheckSingleInstance getInstance() {//第一次检查是否创建过该单例if (instance == null) {//加锁,保证线程安全synchronized (DoubleCheckSingleInstance.class) {if (instance == null) {instance = new DoubleCheckSingleInstance();}}}return instance;}public void doSomething() {}
}
4 静态内部类单例
介绍
- 延迟加载初始化实例instance。
- 线程安全。
- 该方式只适用于静态域的情况。
- 该方式单例不会立即初始化,只有显式调用getInstance()方法时,才会显式转载静态内部类,才会实例化instance。
代码
/*** 静态内部类单例* @author Andya* @date 2021/3/9*/
public class StaticInternalSingleInstance {//静态内部类private static class StaticInternalSingleInstanceHolder{private static final StaticInternalSingleInstance INSTANCE= new StaticInternalSingleInstance();}private StaticInternalSingleInstance() {doSomething();}public static final StaticInternalSingleInstance getInstance() {return StaticInternalSingleInstanceHolder.INSTANCE;}public void doSomething() {}}
5 枚举类单例
介绍
- 不属于延迟加载初始化实例instance。
- 多线程安全。
- 支持序列化机制,从而防止多次实例化。
代码
/*** 枚举型单例* @author Andya* @date 2021/3/9*/
public enum EnumSingleInstance {INSTANCE;public EnumSingleInstance getInstance(){return INSTANCE;}
}
总结
一般在开发应用中,建议使用第1种饿汉式单例,而不推荐使用第2种懒汉式单例,除非明确需要延迟加载时,才会使用第4种静态内部类单例,若涉及到反序列化创建对象时,推荐使用第5种枚举式单例。其他也可以考虑使用第3种双重检锁式单例。
设计模式——单例模式详解相关推荐
- C++设计模式--单例模式详解(懒汉模式、饿汉模式、双重锁)
C++设计模式--单例模式详解(懒汉模式.饿汉模式.双重锁) 应用场景 一.单例模式是什么? 二.使用步骤 1.UML图 2.代码实现 应用场景 通常我们在做通讯的时候,我们跟服务器数据交互,假如每次 ...
- iOS设计模式 ——单例模式详解以及严格单例模式注意点
一.我们常用的单例有哪些? [[UIApplication sharedApplication] statusBarStyle];//系统中的单例模式,通过它获取到状态栏的style [NSNotif ...
- Java设计模式 - 单例模式详解(下)
单例模式引发相关整理 关联线程安全 在多线程下,懒汉式会有一定修改.当两个线程在if(null == instance)语句阻塞的时候,可能由两个线程进入创建实例,从而返回了两个对象.对此,我们可以加 ...
- java connection 单例_Java设计模式之单例模式详解
Java设计模式之单例模式详解 什么是设计模式 设计模式是在大量的实践中总结和理论之后优选的代码结构,编程风格,以及解决问题的思考方式.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可 ...
- 单例模式(单例设计模式)详解
在有些系统中,为了节省内存资源.保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式. 单例模式的定义与特点 单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自 ...
- 单例模式应用场景_三、单例模式详解
4.单例模式详解 4.1.课程目标 1.掌握单例模式的应用场景. 2.掌握IDEA环境下的多线程调试方式. 3.掌握保证线程安全的单例模式策略. 4.掌握反射暴力攻击单例解决方案及原理分析. 5.序列 ...
- 以下属于单例模式的优点的是_三、单例模式详解
4.单例模式详解 4.1.课程目标 1.掌握单例模式的应用场景. 2.掌握IDEA环境下的多线程调试方式. 3.掌握保证线程安全的单例模式策略. 4.掌握反射暴力攻击单例解决方案及原理分析. 5.序列 ...
- python单例模式解析_Python下简易的单例模式详解
Python 下的单例模式 要点: 1.某个类只能有一个实例: 2.它必须自行创建这个实例: 3.它必须自行向整个系统提供这个实例 方法:重写new函数 应该考虑的情况: 1.这个单例的类可能继承了别 ...
- 策略模式(策略设计模式)详解
策略模式(策略设计模式)详解 在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机.乘坐火车.骑自行车或自己开私家车等,超市促销可以釆用打折.送商品.送积分等方法. ...
最新文章
- SSISDB6:参数和环境变量
- 海外对鸿蒙的态度,谷歌、三星挑明态度,国内厂商集体拒绝鸿蒙?任正非将如何应对?...
- java基础--网络编程
- M - Kill the tree 计蒜客 - 42552(2019icpc徐州/树的重心/树形dp)
- ORACLE存储过程中计算某天所在周的周一和周日的方法
- 计算机体系结构_计算机体系结构知识笔记
- mysql数据库优化语句_MySQL优化之三:SQL语句优化
- C#:判断数组中有没有某个值的方法
- c语言五子棋双链表,五子棋的悔棋函数怎么写啊。。。双击鼠标左键悔棋(菠萝镇楼)...
- nmap命令扫描开放端口
- 计算机系统的四种启动方式是,电脑启动方式有几种你知道吗?
- 51单片机 普中V2 数字时钟 电子时钟 万年历 DS1302 LCD1602 AT24C02
- 2019.02.24
- 消防应急照明系统在某数据中心项目的应用
- 【C语言】判断一个浮点数是否等于零
- python 3d图形控件 可交互_Python和Matplotlib:在Jupyter Noteb中使3D plot交互
- linux下如何配置svn,Linux下SVN安装与配置详解
- 购物商城实现点击商品列表某商品,进入其详情页!
- 【每日一题】027 奇妙的数字
- python气象数据可视化学习笔记6——利用python地图库cnmaps绘制地图填色图并白化
热门文章
- centos 安装git_在Centos8上安装Git的方法
- linux那些事之page fault(AMD64架构)(user space)(2)
- 并行计算的一些思考与总结
- windows下python 版本opencv 安装
- functools.reduce() 函数(不同于einops.reduce)
- transform的q、k、v的计算过程
- cookie/storage
- jQuery-事件和应用
- sql查询出的字段切割_SPL 简化 SQL 案例详解:多层固定分组
- Excel 批量处理行高(图文教程) - Excel篇