单例模式
来源:互联网 发布:无线网测试软件 编辑:程序博客网 时间:2024/06/06 17:19
单例模式
回顾一下
- 工厂模式: 女娲造人
- 抽象工厂模式: 厨房,食物,吃货
- 适配器模式: 港版iphone6,充电头,转接头
- 装饰者模式: 各种女朋友
- 观察者模式: 视频网站,美剧
什么是单例模式
单例模式,顾名思义,就是被单例的对象只能有一个实例存在。单例模式的实现方式是,一个类能返回对象的一个引用(永远是同一个) 和 一个获得该唯一实例的方法(必须是静态方法)。用过单例模式,我们可以保证系统中只有一个实例,从而在某些特定的场合下达到节约或者控制系统资源的目的。
单例模式类图
在装饰者模式中,体验了不同的女朋友后,最后你只能拥有一个老婆。
饿汉模式
最常见的单例模式之一。正如其名,很饥渴,所以一上来就需要给它新建一个实例。但这种方法有一个明显的缺点,就是不管有没有调用过获得实例的方法,每次都会创建一个实例。
`
//饿汉模式
public class Wife {
//上来就新建一个实例
private static final Wife wife = new Wife();//默认构造方法 private Wife() {} //获得实例的方法 public static Wife getWife() { return wife; }}
`
懒汉模式
最常见,最简单的单例模式之二,跟饿汉模式是好基友。顾名思义,就是一开始不新建实例,只有当它需要使用的时候,会先判断实例是否为空,如果为空才会新建一个实例来使用。
`
public class Wife {
//一开始没有新建实例
private static Wife wife;private Wife() {} //需要时再建 public static Wife getWife() { if (wife == null) wife = new Wife(); return wife; }}
`
线程安全的懒汉模式
上面的懒汉模式存在一个严重的问题,那就是如果有多个线程并行调用getWife()方法的时候,还是会创建多个实例,单例模式就失效了。那我们只需价格线程同步就好了是吧。(synchronized)
`
public class Wife {
private static Wife;private Wife(){} public static synchronized getWife() { if (wife == null) wife = new Wife(); return wife; }}
`
4.双重检查锁
上诉看似完美的解决了问题,但是它的效率不高,每次调用获得实例的方法getWife()都要进行同步,但是多数情况下是并不需要同步操作的(例如我的wife实例不为空可以直接使用的时候,就不需要给getWife()方法加同步,直接返回wife实例就可以)。所以只需要在第一次新建实例对象的时候,使用同步方法。` //双重锁的getWife()方法 public static Wife getWife() { //第一个检查锁,若不为空直接返回实例对象,为空才进入下一步 if (wife == null) { synchronized(Wife.class) { //第二个检查锁,因为可能有多个线程进入到if语句内 if (wife == null) wife = new Wife(); } } return wife; }`
但是!!! 这还没有结束,主要问题在于wife = new Wife(),因为JVM在执行这句代码时,要做好几件事情,而JVM为了优化代码,有可能造成做这几件事的顺序不固定,从而造成错误。
这个时候我们需要给实例加一个volatile关键字,它的作用就是防止编译器自行优化代码。所以…最终双重检验锁出炉了。
` public class Wife { private volatile static Wife wife; private Wife() {} public static Wife getWife() { if (wife == null) { synchronized(Wife.class) { if (wife == null) { wife = new Wife(); } } } return wife; } }`
静态内部类
上面的方法,实在是太复杂了,而且volatile关键字在某些老版本的jdk中无法正常工作。咋们的换一种方法,即“静态内部类”,这种方式,利用了JVM自身的机制来保证线程安全,因为WifeHolder类是私有的,除了getWife()之外没有其他方式可以访问实例对象,而且只有在调用getWife()时才会去真正创建实例对象。`
public class Wife {
private static class WifeHolder {
private static final Wife wife = new Wife();
}
private Wife(){}public static Wife getWife() { return WifeHolder.wife; }}
`
- 单例、单例模式
- 单例模式-多线程单例模式
- 单件模式(单例模式)
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- PHP模式-单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 单例模式(单子模式)
- 设计模式-单例模式
- [设计模式] 单例模式
- 权限管理--------分配权限
- OpenJudge 1996:登山——题解
- 装饰者模式
- Joseph
- malloc 背后的系统知识
- 单例模式
- mybatis使用foreach语句实现IN查询
- 用深度学习(CNN RNN Attention)解决大规模文本分类问题
- Android新手上路-Apt技术的相关笔记
- 为什么String是不可变的
- 1193: [HNOI2006]马步距离
- 观察者模式
- MapReduce实例----排序
- eclipse debug启动很慢