单例

介绍

  单例模式(Singleton Pattern)是Java中最基础最简单的设计模式之一,这种模式属于创建型模式,提供的就是一种创建对象的方式。这种模式中的单一类创建自己的对象,确保只有一个对象被创建,并且为所有对象提供一个访问它的全局访问点。
  单例模式用来解决频繁创建与销毁实例对象问题,当我们想要控制实例创建个数或者复用实例时,就可以使用单例模式,这样有助于节省系统资源。

特点

  1. 单例类,顾名思义,只有一个实例。
  2. 单例类必须是自己创建自己的唯一实例。
  3. 单例类必须给所有对象提供这个唯一实例。
  4. 构造函数私有。

应用场景

适用范围

  1. 频繁的访问数据库或文件的对象。
  2. 频繁的需要实例化,然后销毁的对象。
  3. 创建对象耗时长且耗资源,但是又需要常用的对象。

使用举例

  1. Windows的任务管理器,每次只能打开一个。
  2. 应用程序的日志应用。
  3. 网上在线人数统计。
  4. 配置文件的访问类。
  5. 数据库的连接池。
  6. 多线程的线程池。
  7. 操作系统的文件系统。

设计思路

  1. 一个类每次都返回唯一的对象(每次返回都是同一个对象实例)。
  2. 提供一个获取该实例的方法。(基本上都是静态方法)
  3. 构造函数私有。

加载分类

  1. 提前加载:在应用开始时就创建单例实例。
  2. 延迟加载:在getInstance()方法首次被调用时才调用单例创建,即需要使用时,才加载创建单例对象实例。

单例分类

1 饿汉式单例

介绍

  1. 类加载时就初始化好实例对象,容易产生垃圾对象,浪费内存。
  2. 无锁,执行效率高。
  3. 天生线程安全,因为类加载时就已初始化好实例。

代码

/*** 饿汉式单例* @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 懒汉式单例

介绍

  1. 饿汉式属于延迟加载初始化。
  2. 若不加锁,则为非线程安全的。
  3. 若加锁,则为线程安全的,但效率很低,基本上每次都要同步。

无锁懒汉式代码

/*** 无锁懒汉式单例,非线程安全* @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次实例化对象。所以多线程应用中,需要来检查实例是否线程安全。

  1. 静态方法锁
public static synchronized Singleton getInstance()
  1. 代码块锁
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 静态内部类单例

介绍

  1. 延迟加载初始化实例instance。
  2. 线程安全。
  3. 该方式只适用于静态域的情况。
  4. 该方式单例不会立即初始化,只有显式调用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 枚举类单例

介绍

  1. 不属于延迟加载初始化实例instance。
  2. 多线程安全。
  3. 支持序列化机制,从而防止多次实例化。

代码

/*** 枚举型单例* @author Andya* @date 2021/3/9*/
public enum EnumSingleInstance {INSTANCE;public EnumSingleInstance getInstance(){return INSTANCE;}
}

总结

  一般在开发应用中,建议使用第1种饿汉式单例,而不推荐使用第2种懒汉式单例,除非明确需要延迟加载时,才会使用第4种静态内部类单例,若涉及到反序列化创建对象时,推荐使用第5种枚举式单例。其他也可以考虑使用第3种双重检锁式单例。

设计模式——单例模式详解相关推荐

  1. C++设计模式--单例模式详解(懒汉模式、饿汉模式、双重锁)

    C++设计模式--单例模式详解(懒汉模式.饿汉模式.双重锁) 应用场景 一.单例模式是什么? 二.使用步骤 1.UML图 2.代码实现 应用场景 通常我们在做通讯的时候,我们跟服务器数据交互,假如每次 ...

  2. iOS设计模式 ——单例模式详解以及严格单例模式注意点

    一.我们常用的单例有哪些? [[UIApplication sharedApplication] statusBarStyle];//系统中的单例模式,通过它获取到状态栏的style [NSNotif ...

  3. Java设计模式 - 单例模式详解(下)

    单例模式引发相关整理 关联线程安全 在多线程下,懒汉式会有一定修改.当两个线程在if(null == instance)语句阻塞的时候,可能由两个线程进入创建实例,从而返回了两个对象.对此,我们可以加 ...

  4. java connection 单例_Java设计模式之单例模式详解

    Java设计模式之单例模式详解 什么是设计模式 设计模式是在大量的实践中总结和理论之后优选的代码结构,编程风格,以及解决问题的思考方式.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可 ...

  5. 单例模式(单例设计模式)详解

    在有些系统中,为了节省内存资源.保证数据内容的一致性,对某些类要求只能创建一个实例,这就是所谓的单例模式. 单例模式的定义与特点 单例(Singleton)模式的定义:指一个类只有一个实例,且该类能自 ...

  6. 单例模式应用场景_三、单例模式详解

    4.单例模式详解 4.1.课程目标 1.掌握单例模式的应用场景. 2.掌握IDEA环境下的多线程调试方式. 3.掌握保证线程安全的单例模式策略. 4.掌握反射暴力攻击单例解决方案及原理分析. 5.序列 ...

  7. 以下属于单例模式的优点的是_三、单例模式详解

    4.单例模式详解 4.1.课程目标 1.掌握单例模式的应用场景. 2.掌握IDEA环境下的多线程调试方式. 3.掌握保证线程安全的单例模式策略. 4.掌握反射暴力攻击单例解决方案及原理分析. 5.序列 ...

  8. python单例模式解析_Python下简易的单例模式详解

    Python 下的单例模式 要点: 1.某个类只能有一个实例: 2.它必须自行创建这个实例: 3.它必须自行向整个系统提供这个实例 方法:重写new函数 应该考虑的情况: 1.这个单例的类可能继承了别 ...

  9. 策略模式(策略设计模式)详解

    策略模式(策略设计模式)详解 在现实生活中常常遇到实现某种目标存在多种策略可供选择的情况,例如,出行旅游可以乘坐飞机.乘坐火车.骑自行车或自己开私家车等,超市促销可以釆用打折.送商品.送积分等方法. ...

最新文章

  1. SSISDB6:参数和环境变量
  2. 海外对鸿蒙的态度,谷歌、三星挑明态度,国内厂商集体拒绝鸿蒙?任正非将如何应对?...
  3. java基础--网络编程
  4. M - Kill the tree 计蒜客 - 42552(2019icpc徐州/树的重心/树形dp)
  5. ORACLE存储过程中计算某天所在周的周一和周日的方法
  6. 计算机体系结构_计算机体系结构知识笔记
  7. mysql数据库优化语句_MySQL优化之三:SQL语句优化
  8. C#:判断数组中有没有某个值的方法
  9. c语言五子棋双链表,五子棋的悔棋函数怎么写啊。。。双击鼠标左键悔棋(菠萝镇楼)...
  10. nmap命令扫描开放端口
  11. 计算机系统的四种启动方式是,电脑启动方式有几种你知道吗?
  12. 51单片机 普中V2 数字时钟 电子时钟 万年历 DS1302 LCD1602 AT24C02
  13. 2019.02.24
  14. 消防应急照明系统在某数据中心项目的应用
  15. 【C语言】判断一个浮点数是否等于零
  16. python 3d图形控件 可交互_Python和Matplotlib:在Jupyter Noteb中使3D plot交互
  17. linux下如何配置svn,Linux下SVN安装与配置详解
  18. 购物商城实现点击商品列表某商品,进入其详情页!
  19. 【每日一题】027 奇妙的数字
  20. python气象数据可视化学习笔记6——利用python地图库cnmaps绘制地图填色图并白化

热门文章

  1. centos 安装git_在Centos8上安装Git的方法
  2. linux那些事之page fault(AMD64架构)(user space)(2)
  3. 并行计算的一些思考与总结
  4. windows下python 版本opencv 安装
  5. functools.reduce() 函数(不同于einops.reduce)
  6. transform的q、k、v的计算过程
  7. cookie/storage
  8. jQuery-事件和应用
  9. sql查询出的字段切割_SPL 简化 SQL 案例详解:多层固定分组
  10. Excel 批量处理行高(图文教程) - Excel篇