单例模式(饿汉式和懒汉式)
来源:互联网 发布:7405单片机管脚图 编辑:程序博客网 时间:2024/06/10 01:08
以前学习单例的时候,只理解了简单部分。这次看DRP,对单例的饿汉式和懒汉式有了一些认识和对比。
在实际的开发中,有些地方需要一个类只有一个实例。比如:网站在线人数的计数器,再比如IDE中的工具箱之类的等等。当需要这个类只有一个实例时,我们就需要使用到单例模式。单例模式有两种实现方式:懒汉式(延迟加载)和 饿汉式(预加载)。
目前遇到的情况使用饿汉式的比较多,也因为它比较简单。代码:
饿汉式:在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。这里getInstance()是static的,不用同步(类加载时已初始化,不会有多线程的问题)饿汉式程序运行过程中会节省时间,但是实例不管有没有用到都会占用空间。在这方面懒汉式似乎比饿汉式优化。我们先看看代码:
比较懒,在类加载时,不创建实例,因此类加载速度快,但运行时获取对象的速度慢。这里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的对象——单例失败!
对于这种情况,我们很容易就想到加锁来解决。那么加锁后是怎么样的?
getInstance()加上同步锁,一个线程必须等待另外一个线程创建完成后才能使用这个方法,这就保证了单例的唯一性。但是还有出现这样一个性能问题:每次调用getInstants时都需要加锁,会降低运行速度。所以我们还可以进一步改进。 这样的方法可以双重锁定。我们一般用让线程每次都加锁,而只是实例未被创建的时候再加锁处理,同时也能保证多线程的安全。为什么要进行两次instance==null的判断,这个交给大家自己想一下吧。就按照上面线程A和线程B这样的方式。最后,总结一下饿汉式和懒汉式的区别:饿汉式类加载时已初始化,不会有多线程的问题,使用简单。懒汉式是在需要时才对类进行实例化,但是有多线程问题,需要该考虑怎么加锁的问题。
0 0
- 单例模式-饿汉式和懒汉式
- 单例模式(懒汉式和饿汉式)
- 单例模式(懒汉式和饿汉式)
- 单例模式(懒汉式和饿汉式)
- 单例模式(饿汉式和懒汉式)
- java单例模式(懒汉式和饿汉式)
- 单例模式(饿汉式和懒汉式)
- 单例模式(懒汉式和饿汉式)
- 单例设计模式(饿汉式和懒汉式)
- 单例模式(饿汉式&懒汉式)
- 设计模式-单例模式之饿汉式和懒汉式
- 设计模式------单例模式之饿汉式和懒汉式
- 单例模式两种模式--饿汉式和懒汉式
- 单例模式的懒汉式和饿汉式
- Java单例模式:饿汉式和懒汉式的实现
- 单例模式的懒汉式和饿汉式
- Java单例模式:饿汉式和懒汉式的实现
- Java单例模式:饿汉式和懒汉式的实现
- 排列若干个字符串,判断是否首尾可以连接在一起
- 用shell脚本监控进程是否存在 不存在则启动的实例
- 树莓派调整分区大小
- LinearLayout(线性布局)
- CodingNet - Learning - 18
- 单例模式(饿汉式和懒汉式)
- Android SQLite数据库的基本使用
- Linux分页机制之概述--Linux内存管理(六)
- 自己写的《带着媳妇去冒险》安卓手游
- java 代理模式,JDK动态代理,SpringAOP的实现
- **高精度模板**
- git入门简单介绍
- 短文本相似度度量
- Activity的四种启动模式