单例模式(饿汉式和懒汉式)
以前学习单例的时候,只理解了简单部分。这次看DRP,对单例的饿汉式和懒汉式有了一些认识和对比。
在实际的开发中,有些地方需要一个类只有一个实例。比如:网站在线人数的计数器,再比如IDE中的工具箱之类的等等。当需要这个类只有一个实例时,我们就需要使用到单例模式。单例模式有两种实现方式:懒汉式(延迟加载)和 饿汉式(预加载)。
目前遇到的情况使用饿汉式的比较多,也因为它比较简单。代码:
- public class ClientManager {
- private static ClientManager instance = new ClientManager(); //静态私有成员,已初始化
- public ClientManager(){ }
- public static ClientManager getInstance(){ //静态,不用同步(类加载时已初始化,不会有多线程的问题)
- return instance;
- }
- }
饿汉式:在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。这里getInstance()是static的,不用同步(类加载时已初始化,不会有多线程的问题)
饿汉式程序运行过程中会节省时间,但是实例不管有没有用到都会占用空间。在这方面懒汉式似乎比饿汉式优化。我们先看看代码:
- public class ClientManager
- {
- private static ClientManager instance = null;
- private ClientManager(){
- }
- public static ClientManager getInstance(){ //静态,同步,公开访问点
- if(instance == null){
- return new ClientManager();
- }
- return instance;
- }
- }
比较懒,在类加载时,不创建实例,因此类加载速度快,但运行时获取对象的速度慢。这里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的对象——单例失败!
对于这种情况,我们很容易就想到加锁来解决。那么加锁后是怎么样的?
- public class ClientManager{
- private static ClientManager instance = null;
- public synchronized static ClientManager getInstance() { //给方法加锁
- if(instance == null) {
- instance = new ClientManager();
- }
- return instance;
- }
- private ClientManager() {
- }
- }
getInstance()加上同步锁,一个线程必须等待另外一个线程创建完成后才能使用这个方法,这就保证了单例的唯一性。但是还有出现这样一个性能问题:每次调用getInstants时都需要加锁,会降低运行速度。所以我们还可以进一步改进。
- public class ClientManager {
- private static ClientManager instance = null;
- public static ClientManager getInstance() {
- if (instance == null) {
- synchronized (ClientManager.class) {
- if(instance == null) {
- instance = new ClientManager();
- }
- }
- }
- return instance;
- }
- private ClientManager() {
- }
这样的方法可以双重锁定。我们一般用让线程每次都加锁,而只是实例未被创建的时候再加锁处理,同时也能保证多线程的安全。为什么要进行两次instance==null的判断,这个交给大家自己想一下吧。就按照上面线程A和线程B这样的方式。
最后,总结一下饿汉式和懒汉式的区别:饿汉式类加载时已初始化,不会有多线程的问题,使用简单。懒汉式是在需要时才对类进行实例化,但是有多线程问题,需要该考虑怎么加锁的问题。
单例模式(饿汉式和懒汉式)相关推荐
- 单例模式饿汉式与懒汉式详解
单例模式饿汉式与懒汉式详解 步骤: 私有构造方法,使得在类的外部不能调用此方法,限制产生多个对象 类初始化时,区分饿汉式与懒汉式的区别 对外部提供调用方法,将创建的对象返回,只能通过类来调用 饿汉式: ...
- Singleton模式(单例模式) 饿汉式和懒汉式
目的:整个应用中有且只有一个实例,所有指向该类型实例的引用都指向这个实例. 好比一个国家就只有一个皇帝(XXX),此时每个人叫的"皇帝"都是指叫的XXX本人; 常见单例模式类型: ...
- 单例模式——饿汉式和懒汉式
单例模式:一个类只允许存在唯一的对象,并提供它的访问方式 创建思路: 1.禁止在类的外部创建对象:私有化构造函数 2.在类的内部提供唯一的对象:静态成员变量 3.提供访问唯一对象的方法:静态成员函数 ...
- Java-Day12 面向对象的三大特征之封装、继承,单例模式(饿汉式、懒汉式)、方法重写 (覆盖)、注解 (annotation)、super关键字、对象的创建流程超详细
目录 1. 面向对象的三大特征之封装 1.1 封装的含义 1.2 封装的目的 1.3 封装的优点 1.4 封装的实现过程 1.5 拓展知识:JavaBean 2. 面向对象的三大特征之继承 2.1 继 ...
- Java中单例模式—饿汉式和懒汉式
所谓单例模式就是为了确保类在内存中只有一个对象,之所以会出现单例模式是因为,单例模式在系统内存中只存在一个对象,可以节约资源 目录 一.饿汉式 二.懒汉式 一.饿汉式 该方式在开发中是经常用的,因为这 ...
- 【学习笔记】【C++整理A】【总】单例模式-饿汉式、懒汉式;
文章目录 一.语言分类: 三.基础A:- 函数重载.默认参数.extern "C".重复包含 1.函数重载 2.默认参数 3.extern "C" 4.防止重复 ...
- Java实现单例模式之饿汉式、懒汉式、枚举式,带测试。
Java实现单例的3种普遍的模式,饿汉式.懒汉式.枚举式. 具体代码如下: package com.lcx.mode;/*** * 饿汉式单例,不管以后用不用这个对象,我们一开始就创建这个对象的实例, ...
- 单例模式饿汉式/懒汉式的区别
単例设计模式(Singleton Pattern): 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法. 如果我们要 ...
- 设计模式—单例模式(饿汉式、懒汉式)
目录 一.什么是单例模式? 二.单例模式的类型 三.单例模式的公共特征 四.单例模式-饿汉式 五.单例模式-懒汉式 5.1 懒汉式实现方式一(有问题不提倡使用) 5.2 懒汉式实现方式二(提倡使用) ...
最新文章
- git的团队协作开发
- Qt之进程间通信(IPC)
- PX4/Pixhawk---uORB深入理解和应用
- 【转】Castle Windsor之组件注册
- html5中如何去掉input type date默认
- 小心点,别被当成垃圾回收了。
- php从注册列表卸载,MSSQL_彻底删除SQL Server注册表的方法,一般在卸载完数据库时,大家 - phpStudy...
- linux java weblogic,Linux java 安装问题
- [RMAN]异机恢复实验
- mysql主流版本2020_mysql高级2020.7.12-2020.7.13
- UVA10295 POJ2403 ZOJ1902 Hay Points【map】
- Spring Boot 推荐的基础 POM 文件
- SQL Server SQL语句调优技巧
- 探索Android FrameWork底层开发视频全套
- 【源码】MATLAB的专业绘图工具
- Cisco IOS镜像文件的下载地址
- 华东师范大学夏令营复习计划总结
- Unity 反转法线,在 Hierarchy 视图对象的快捷菜单中增加 Flip Mesh Normals(反转网格法线)项...
- 组装一台电脑需要哪些基本配件?
- httprunner3.x使用过程中遇到的问题
热门文章
- python操作界面_Python使用PyQt5的Designer工具创建UI界面
- java 判断对象是否是xml格式_java对象与xml格式之间的转换
- MySQL倒序如何避免filesort_如何避免mysql查询的filesort?
- 操作系统的msxml组件版本过低_Zabbix 5.0 LTS 版本安装
- PoE交换机的4种连接方法
- 【渝粤教育】国家开放大学2018年春季 0004-22T有机合成单元反应 参考试题
- [渝粤教育] 中国地质大学 计算机系统结构(新) 复习题
- 【渝粤教育】广东开放大学 法理学 形成性考核 (46)
- 【渝粤题库】广东开放大学 Java高级编程技术 形成性考核
- 【渝粤题库】广东开放大学 文化产业经济学 形成性考核