单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。

这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问不需要实例化该类的对象

注意:

  • 1、单例类只能有一个实例。
  • 2、单例类必须自己创建自己的唯一实例
  • 3、单例类必须给所有其他对象提供这一实例

介绍

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

主要解决:一个全局使用的类频繁地创建与销毁

何时使用:当您想控制实例数目节省系统资源的时候。

如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。

关键代码:构造函数是私有的。

应用实例:

  • 1、一个班级只有一个班主任。
  • 2、Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。
  • 3、一些设备管理器常常设计为单例模式,比如一个电脑有两台打印机,在输出的时候就要处理不能两台打印机打印同一个文件。

优点:

  • 1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
  • 2、避免对资源的多重占用(比如写文件操作)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

使用场景:

  • 1、要求生产唯一序列号。
  • 2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
  • 3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
  • Spring中创建的Bean实例默认都是单例。
  • Java-Web中,一个Servlet类只有一个实例

注意事项:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

 单例模式的几种实现方式

1、懒汉式,线程不安全

 2、懒汉式,线程安全

3、饿汉式

 4、双检锁/双重校验锁  DCL(懒汉式

 5、登记式/静态内部类 (懒汉式

6、枚举 

---------------------------------------------------------------------------------------------------------------------------------

1、懒汉式,线程不安全

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作

接下来介绍的几种实现方式都支持多线程,但是在性能上有所差异

2、懒汉式,线程安全 支持多线程

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种方式具备很好的 lazy loading(懒加载),能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。

4、双检锁/双重校验锁(DCL,即 double-checked locking)

JDK 版本:JDK1.5 起

是否 Lazy 初始化:

是否多线程安全:

实现难度:较复杂

描述:这种方式采用双锁机制安全且在多线程情况下能保持高性能
getInstance() 的性能对应用程序很关键。

5、登记式/静态内部类

是否 Lazy 初始化:

是否多线程安全:

实现难度:一般

描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况双检锁方式可在实例域需要延迟初始化时使用。
这种方式同样利用了 classloader (类加载)机制来保证初始化 instance(实例) 时只有一个线程,它跟第 3 种方式不同的是:第 3 种方式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果),而这种方式是 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。想象一下,如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。这个时候,这种方式相比第 3 种方式就显得很合理。

6、枚举

JDK 版本:JDK1.5 起

是否 Lazy 初始化:

是否多线程安全:

实现难度:

描述:这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制绝对防止多次实例化
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还自动支持序列化机制防止反序列化重新创建新的对象绝对防止多次实例化。不过,由于 JDK1.5 之后才加入 enum 特性,用这种方式写不免让人感觉生疏,在实际工作中,也很少用
不能通过 reflection attack 来调用私有构造方法。

经验之谈:一般情况下,不建议使用第 1 种和第 2 种懒汉方式,建议使用第 3 种饿汉方式。只有在要明确实现 lazy loading (懒加载)效果时,才会使用第 5 种登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。

单例模式:懒汉式 饿汉式 双检锁 登记式 枚举式 详细讲解相关推荐

  1. Spring框架学习day_01: 框架配置方式/ 管理对象的作用域/ 生命周期/ 组件扫描/ 单例模式:“懒汉式“,“饿汉式“

    1. Spring框架的作用 Spring框架的主要作用是创建对象和管理对象. 创建对象:类似于User user = new User(); 管理对象:随时可以通过Spring框架获取对象,甚至Sp ...

  2. 单例模式(懒汉模式-双检锁、饿汉模式、静态内部类模式)-详细

    文章目录 前言 单例模式(懒汉模式-双检锁.饿汉模式.静态内部类模式)-详细 01 单例模式是什么? 02 单例模式的好处? 03 单例模式的三种模式 03::01 懒汉模式 03::01::01 问 ...

  3. Java的懒汉式双检锁单例模式

    Java的懒汉式双检锁单例模式 文章目录 Java的懒汉式双检锁单例模式 一. 实现一个双检锁 二. 为什么线程不安全 三. 关于指令重排序 四. 关于原子操作 五. 实现线程安全的双检锁 首先回忆一 ...

  4. 单例模式之饿汉式与懒汉式

    常见的单例模式 本文仅讲解单例模式中的饿汉式和懒汉式(双检索) 文章目录 常见的单例模式 前言 一.单例模式的优缺点 二.详解懒汉式.饿汉式 1.饿汉式 2.懒汉式(双检锁) 总结 前言 先来简单的说 ...

  5. 单例模式:饿汉式vs懒汉式

    单例模式是指,在代码运行时,保证某一个类只能被创建一个对象,不可以被创建第二次对象. 饿汉式: 1.先将类中的构造器私有化,用private修饰,防止在外界创建对象 例: private Test() ...

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

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

  7. 单例模式之饿汉式单例模式

    单例模式之饿汉式单例模式 单例模式三要素: 1.私有的静态属性,这主要是为了存储类唯一的实例 2.公共的静态方法,这主要是为了提供给外键生成获取单例的方法 3.用于限制类再次实例话的措施.一般会私有化 ...

  8. sentinel里的双检锁

    单例模式有很多种,饿汉式,懒汉式,双检锁,公司里大部分都是选择了双检锁,其中sentinel的ContextUtil源码里就有相关的实现: protected static Context trueE ...

  9. 单例模式之懒汉式/饿汉式/结合二者之优的模式

    单例模式主要用来产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例. 两个好处: 对于频繁使用的对象,可以省略new操作花费的时间 new的次数少了,对系统内存的使用频率就小了,那么GC压力 ...

最新文章

  1. C语言字符char和整型int的关系
  2. Flink 在小红书推荐系统中的应用
  3. java拳皇地下城_拳皇(Java简单的小程序)代码实例
  4. when is SAP UI5 url hash changed in browser
  5. 程序员最常见的谎话,太准了
  6. 预约 .NET Conf: Focus on F# 活动,赢得官方周边!
  7. 巴菲特午宴中标者孙宇晨与王小川隔空互怼 还要对赌100个比特币?
  8. Redis基础(六)——事务
  9. Python之 面向对象封装案例
  10. day20线程Thread的sleep方法
  11. 基于移动最小二乘的图像变形
  12. Max Script|多边形的控制
  13. 百度地图开发:根据指定手绘图纸照片行政区划自定义绘制对应区域边界生成geoJOSN的解决方案
  14. 主域名跳转到带www的域名方法,以及对seo有什么影响?
  15. Python输出[m,n]既能被3整除又能被7整除的数的个数
  16. matplotlib图表多曲线多纵轴绘制工具方法
  17. 2017第九届广州国际园林机械与园艺工具展 2017第九届广州国际园林景观与美好人居博览会 第九届广州国际花卉盆栽及花店花园用品展览会 2017中国花卉展览会 第九届广州国际绿化苗木展会刊(参展商名录
  18. js中获取只包含一种字符的最长非空子字符串的长度
  19. 《华仪酒店管理系统》项目研发性总结
  20. HL7 标准及实现指南 必看的网址

热门文章

  1. SkyDrive 体验
  2. APP网络传输安全测试
  3. 不怕舔狗有耐心,就怕卷狗有文化(bugku社工-进阶收集)
  4. DW软件如何使用一串特殊代码让你的导航多种角度旋转
  5. 使用 MEME 分析不同类型的 NB-ARC 结构域中 Motif 的差异
  6. 谷歌插件之蓝湖代码生成器,iOS,Android,Swift,Flutter
  7. 【实验分享】Switch基本配置
  8. python大学公众号_几个清华、交大学霸的公众号,值得关注
  9. python psi指标
  10. 利用4位led显示本机秒表时间的单片机c语言程序,基于单片机的一个2位的led数码显示作为_秒表_设计.doc...