单例模式(Singleton)

Singleton模式确保每个Java类加载器只能有一个已有的实例并提供对其的全局访问,单例可以节省内存加快对象访问速度

适用场景

  • 需要频繁实例化然后销毁的对象
  • 创建对象耗时长或占用资源大,但又要经常用到的对象
  • 带有状态的工具类对象
  • 频繁访问数据库或文件的对象,一次实例化多次使用

单例种类

  1. 饿汉式:类加载的时候就被初始化,静态字段中实例化
  2. 懒汉式:延迟加载,调用getInstance()方法时实例化
  3. 双重检查锁:延迟加载,对上一个进行优化的方式
    以上都是线程安全的

代码示例

饿汉式

/*** 饿汉式,急切初始化静态实例保证线程安全* <p>* 优点:没有线程安全问题,简单* 缺点:提前初始化会延长类加载器加载类的时间;如果不使用会浪费空间;不能传递参数进行实例化** @author July* @date 2020/10/21*/
public final class HungrySingleton {/*** 类的静态实例,final的*/private static final HungrySingleton INSTANCE = new HungrySingleton();/*** 私有构造,没有其它方式能初始化类*/private HungrySingleton() {}/*** 静态方法提供用户调用以获取类的实例** @return 单例对象*/public static HungrySingleton getInstance() {return INSTANCE;}
}

懒汉式(私有内部类方式)

/*** 懒汉式,在需要的时候才初始化单例对象** 优点:延迟加载的情况下解决线程安全问题(Effective Java推荐写法)** @author July* @date 2020/10/21*/
public final class LazyLoadedSingleton {/*** 私有构造*/private LazyLoadedSingleton() {System.out.println("init LazyLoadedSingleton");}/*** @return 单例对象*/public static LazyLoadedSingleton getInstance() {return HelperHolder.INSTANCE;}/*** 【重点】内部类HelperHolder被引用的时间不会早于getInstance()被调用的时间,* 所以线程安全,不需要特殊的语言结构(例如volatile或synchronized)。*/private static class HelperHolder {public static final LazyLoadedSingleton INSTANCE = new LazyLoadedSingleton();}
}

懒汉式(synchronized方式)

/*** 单例是延迟加载,这里使用synchronized进行同步保证线程安全* <p>* 注意:如果是由反射创建的,那么将不会在同一个类加载器中创建一个单例,而是创建多个选项** @author July* @date 2020/10/21*/
public final class LazyLoadedSingleton2 {private static LazyLoadedSingleton2 instance;private LazyLoadedSingleton2() {}/*** 实例仅在第一次调用时创建*/public static synchronized LazyLoadedSingleton2 getInstance() {if (instance == null) {instance = new LazyLoadedSingleton2();}return instance;}
}

双重检查锁

/*** 双重检查锁* <p/>* 参考:http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html** @author July* @date 2020/10/21*/
public final class DoubleCheckLockingSingleton {private static volatile DoubleCheckLockingSingleton instance;/*** 私有构造防止客户端实例化*/private DoubleCheckLockingSingleton() {// note 防止通过反射调用实例化if (instance != null) {throw new IllegalStateException("Already initialized.");}}/*** 获取单例对象** @return*/public static DoubleCheckLockingSingleton getInstance() {// 局部变量将性能提高25%,《Effective Java, Second Edition》推荐, p. 283-284DoubleCheckLockingSingleton result = instance;// 单例双重检查// 第一重if (result == null) {synchronized (DoubleCheckLockingSingleton.class) {result = instance;// 第二重if (result == null) {instance = result = new DoubleCheckLockingSingleton();}}}return result;}
}

FAQ

  • 单例多种实现方式中为什么要用双重检查锁的方式来实现单例?
    在延迟加载中,保证线程安全可以直接在getInstance()方法中直接使用synchronized来保证线程安全,但性能一个问题,也就是说每次调用getInstance()方法都需要线程同步(加锁其实只需要在第一次初始化的时候用到),性能不高

更多内容可以参考我的另一篇文章:单例模式之双重检查锁(double check locking)的发展历程

如果你喜欢我的文章,记得一键三连(不要下次一定)

一文理解设计模式--单例模式(Singleton)相关推荐

  1. Android设计模式——单例模式(Singleton)

    二十三种设计模式分为三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元 ...

  2. 深入理解设计模式-单例模式(饿汉单例模式、懒汉单例模式、双锁单例模式)

    深入理解设计模式-双锁单例模式 文章目录 一.什么是单例模式 二.应用场景 三.优缺点 四.代码实现 总结 结尾 一.什么是单例模式 单例模式是一种常用的软件设计模式,其定义是单例对象的类只能允许一个 ...

  3. 常见设计模式—单例模式(Singleton)

    前言 好久没写东西了,但是想着无论什么事还是要坚持自己初心要坚持的东西.写东西不能断! 对于常用的23种设计模式,这里笔者会根据自己学习和出现频率.重要程度进行学习记录吧.并且每种设计模式可能会根据暂 ...

  4. C++设计模式--单例模式(Singleton)及单例通用模板

    概述 C++中的单例模式应该是设计模式中最简单的了,在编码中常见到.那么,简单的总结下 C++中的单例模式写法,以及根据单例模式扩展后的一些写法,最后还有单例的通用模板,可用于快捷创建一个单例类. 单 ...

  5. 设计模式 -- 单例模式(Singleton)

    写在前面的话:读书破万卷,编码如有神 -------------------------------------------------------------------- 主要内容包括: 初始单例 ...

  6. JAVA设计模式-单例模式(Singleton)线程安全与效率

    一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...

  7. 设计模式——单例模式(Singleton)

    保证一个类仅有一个实例,并提供一个访问它的全局访问点.--DP UML类图 模式说明 个人认为单例模式是所有设计模式中最为简单的一个模式,因为实现这个模式仅需一个类,而不像其他模式需要若干个类.这个模 ...

  8. Python 设计模式: 单例模式(singleton pattern)

    2019独角兽企业重金招聘Python工程师标准>>> 如果想在整个程序的运行过程中,某个类只有一个实例的话,可以通过单例模式来实现. 在 Python 中实现单例模式有很多种方式, ...

  9. 解读设计模式----单例模式(Singleton Pattern)

    单例模式可以保证一个类有且只有一个实例,并提供一个访问它的全局访问点.在程序设计中,有很多情况需要确保一个类只能有一个实例.从这句话可以看出,Singleton模式的核心:如何控制用户使用new对一个 ...

最新文章

  1. Ubuntu 16.04安装Zabbix 3.2 版本
  2. Python+selenium 自动化-获取当前页面的url地址,打开指定的url地址
  3. SpringBoot(Thymeleaf)前端html页面直接的传参和判定
  4. better-scroll 上拉加载,下拉刷新(解决移动端长页面卡顿)
  5. leecode-数组-27Remove Element-java
  6. LiveVideoStack 2021招聘季
  7. Debug ASP.NET Core 2.0源代码
  8. 有var d = new Date(‘20xx-m-09‘),可以设置为m+1月份的操作是?
  9. JAVA Web基础6-EL表达式与JSTL标签库
  10. 15b万用表怎么测电容_指针式万用表和数字式万用表的使用与口诀,值得收藏!...
  11. 为Windows添加日志事件
  12. JavaScript中清空数组的三种方式
  13. apms阅卷系统服务器,apms全通纸笔王网上阅卷系统操作流程
  14. GSM、UMTS和LTE网络;FDD,TDD双工模式
  15. Oracle重建控制文件
  16. 如何在Mac上设置iCloud
  17. Facebook内战:关于欲望、天才和背叛的故事
  18. ISP—自动白平衡(AWB)
  19. mysql生成18位纯数字id_MySQL实现注册时随机生成数字id,类似于注册qq时随机生成qq号...
  20. 简单自定义协议的封包和解包

热门文章

  1. php打印预览jquery,php 实现打印预览的功能
  2. 从日常代码质量检查工作中感受工作中的乐趣、生活的乐趣
  3. ubuntu install opencv
  4. “绿色高效 模块智能”金融业数据中心系列规范发布会将于12月7日召开
  5. Python中list(列表)、tuple(元组)、dict(字典)的基本操作快速入门
  6. 感谢党,软考过了。系统集成项目管理project师
  7. MySQL常用函数系列之九:日期和时间函数 函数(4)
  8. 源码安装 MariaDB
  9. 深入理解es module
  10. 创业者需要知道的50句话