以前学习单例的时候,只理解了简单部分。这次看DRP,对单例的饿汉式和懒汉式有了一些认识和对比。

在实际的开发中,有些地方需要一个类只有一个实例。比如:网站在线人数的计数器,再比如IDE中的工具箱之类的等等。当需要这个类只有一个实例时,我们就需要使用到单例模式。单例模式有两种实现方式:懒汉式(延迟加载)和 饿汉式(预加载)。

目前遇到的情况使用饿汉式的比较多,也因为它比较简单。代码:

[java] view plaincopy
  1. public class ClientManager {
  2. private static ClientManager instance = new ClientManager();   //静态私有成员,已初始化
  3. public ClientManager(){ }
  4. public static ClientManager getInstance(){     //静态,不用同步(类加载时已初始化,不会有多线程的问题)
  5. return instance;
  6. }
  7. }

饿汉式:在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。这里getInstance()是static的,不用同步(类加载时已初始化,不会有多线程的问题)

饿汉式程序运行过程中会节省时间,但是实例不管有没有用到都会占用空间。在这方面懒汉式似乎比饿汉式优化。我们先看看代码:

[java] view plaincopy
  1. public class ClientManager
  2. {
  3. private static ClientManager instance = null;
  4. private ClientManager(){
  5. }
  6. public static  ClientManager getInstance(){     //静态,同步,公开访问点
  7. if(instance == null){
  8. return new ClientManager();
  9. }
  10. return instance;
  11. }
  12. }

比较懒,在类加载时,不创建实例,因此类加载速度快,但运行时获取对象的速度慢。这里getInstance()是static的。我们来想象一下:要使用ClientManager,直接调用类的getInstance()方法。第一次的时候发现instance是null,然后就新建一个对象,返回出去;第二次再使用的时候,因为这个instance是static的,所以已经不是null了,因此不会再创建对象,直接将其返回。那么为什么有同步的问题?

线程A希望使用ClientManager,调用getInstance()方法。因为是第一次调用,A就发现instance是null的,于是它开始创建实例,就在这个时候,CPU发生时间片切换,线程B开始执行,它要使用ClientManager,调用getInstance()方法,同样检测到instance是null——注意,这是在A检测完之后切换的,也就是说A并没有来得及创建对象——因此B开始创建。B创建完成后,切换到A继续执行,因为它已经检测完了,所以A不会再检测一遍,它会直接创建对象。这样,线程A和B各自拥有一个ClientManager的对象——单例失败!

对于这种情况,我们很容易就想到加锁来解决。那么加锁后是怎么样的?

[java] view plaincopy
  1. public class ClientManager{
  2. private static ClientManager instance = null;
  3. public synchronized static ClientManager getInstance() {     //给方法加锁
  4. if(instance == null) {
  5. instance = new ClientManager();
  6. }
  7. return instance;
  8. }
  9. private ClientManager() {
  10. }
  11. }

getInstance()加上同步锁,一个线程必须等待另外一个线程创建完成后才能使用这个方法,这就保证了单例的唯一性。但是还有出现这样一个性能问题:每次调用getInstants时都需要加锁,会降低运行速度。所以我们还可以进一步改进。

[java] view plaincopy
  1. public class ClientManager {
  2. private  static ClientManager instance = null;
  3. public static ClientManager getInstance() {
  4. if (instance == null) {
  5. synchronized (ClientManager.class) {
  6. if(instance == null) {
  7. instance = new ClientManager();
  8. }
  9. }
  10. }
  11. return instance;
  12. }
  13. private ClientManager() {
  14. }

这样的方法可以双重锁定。我们一般用让线程每次都加锁,而只是实例未被创建的时候再加锁处理,同时也能保证多线程的安全。为什么要进行两次instance==null的判断,这个交给大家自己想一下吧。就按照上面线程A和线程B这样的方式。

最后,总结一下饿汉式和懒汉式的区别:饿汉式类加载时已初始化,不会有多线程的问题,使用简单。懒汉式是在需要时才对类进行实例化,但是有多线程问题,需要该考虑怎么加锁的问题。

单例模式(饿汉式和懒汉式)相关推荐

  1. 单例模式饿汉式与懒汉式详解

    单例模式饿汉式与懒汉式详解 步骤: 私有构造方法,使得在类的外部不能调用此方法,限制产生多个对象 类初始化时,区分饿汉式与懒汉式的区别 对外部提供调用方法,将创建的对象返回,只能通过类来调用 饿汉式: ...

  2. Singleton模式(单例模式) 饿汉式和懒汉式

    目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例. 好比一个国家就只有一个皇帝(XXX),此时每个人叫的"皇帝"都是指叫的XXX本人; 常见单例模式类型: ...

  3. 单例模式——饿汉式和懒汉式

    单例模式:一个类只允许存在唯一的对象,并提供它的访问方式 创建思路: 1.禁止在类的外部创建对象:私有化构造函数 2.在类的内部提供唯一的对象:静态成员变量 3.提供访问唯一对象的方法:静态成员函数 ...

  4. Java-Day12 面向对象的三大特征之封装、继承,单例模式(饿汉式、懒汉式)、方法重写 (覆盖)、注解 (annotation)、super关键字、对象的创建流程超详细

    目录 1. 面向对象的三大特征之封装 1.1 封装的含义 1.2 封装的目的 1.3 封装的优点 1.4 封装的实现过程 1.5 拓展知识:JavaBean 2. 面向对象的三大特征之继承 2.1 继 ...

  5. Java中单例模式—饿汉式和懒汉式

    所谓单例模式就是为了确保类在内存中只有一个对象,之所以会出现单例模式是因为,单例模式在系统内存中只存在一个对象,可以节约资源 目录 一.饿汉式 二.懒汉式 一.饿汉式 该方式在开发中是经常用的,因为这 ...

  6. 【学习笔记】【C++整理A】【总】单例模式-饿汉式、懒汉式;

    文章目录 一.语言分类: 三.基础A:- 函数重载.默认参数.extern "C".重复包含 1.函数重载 2.默认参数 3.extern "C" 4.防止重复 ...

  7. Java实现单例模式之饿汉式、懒汉式、枚举式,带测试。

    Java实现单例的3种普遍的模式,饿汉式.懒汉式.枚举式. 具体代码如下: package com.lcx.mode;/*** * 饿汉式单例,不管以后用不用这个对象,我们一开始就创建这个对象的实例, ...

  8. 单例模式饿汉式/懒汉式的区别

    単例设计模式(Singleton Pattern): 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法. 如果我们要 ...

  9. 设计模式—单例模式(饿汉式、懒汉式)

    目录 一.什么是单例模式? 二.单例模式的类型 三.单例模式的公共特征 四.单例模式-饿汉式 五.单例模式-懒汉式 5.1 懒汉式实现方式一(有问题不提倡使用) 5.2 懒汉式实现方式二(提倡使用) ...

最新文章

  1. git的团队协作开发
  2. Qt之进程间通信(IPC)
  3. PX4/Pixhawk---uORB深入理解和应用
  4. 【转】Castle Windsor之组件注册
  5. html5中如何去掉input type date默认
  6. 小心点,别被当成垃圾回收了。
  7. php从注册列表卸载,MSSQL_彻底删除SQL Server注册表的方法,一般在卸载完数据库时,大家 - phpStudy...
  8. linux java weblogic,Linux java 安装问题
  9. [RMAN]异机恢复实验
  10. mysql主流版本2020_mysql高级2020.7.12-2020.7.13
  11. UVA10295 POJ2403 ZOJ1902 Hay Points【map】
  12. Spring Boot 推荐的基础 POM 文件
  13. SQL Server SQL语句调优技巧
  14. 探索Android FrameWork底层开发视频全套
  15. 【源码】MATLAB的专业绘图工具
  16. Cisco IOS镜像文件的下载地址
  17. 华东师范大学夏令营复习计划总结
  18. Unity 反转法线,在 Hierarchy 视图对象的快捷菜单中增加 Flip Mesh Normals(反转网格法线)项...
  19. 组装一台电脑需要哪些基本配件?
  20. httprunner3.x使用过程中遇到的问题

热门文章

  1. python操作界面_Python使用PyQt5的Designer工具创建UI界面
  2. java 判断对象是否是xml格式_java对象与xml格式之间的转换
  3. MySQL倒序如何避免filesort_如何避免mysql查询的filesort?
  4. 操作系统的msxml组件版本过低_Zabbix 5.0 LTS 版本安装
  5. PoE交换机的4种连接方法
  6. 【渝粤教育】国家开放大学2018年春季 0004-22T有机合成单元反应 参考试题
  7. [渝粤教育] 中国地质大学 计算机系统结构(新) 复习题
  8. 【渝粤教育】广东开放大学 法理学 形成性考核 (46)
  9. 【渝粤题库】广东开放大学 Java高级编程技术 形成性考核
  10. 【渝粤题库】广东开放大学 文化产业经济学 形成性考核