单例模式
来源:互联网 发布:java 高并发http接口 编辑:程序博客网 时间:2024/05/15 12:22
单例模式也许是最常见的一种设计模式了。看起来简单,实际上如果不注意细节,产生的问题,相对还是有些复杂的。
在软件系统中,我们希望某些类始终保持最多一个实例对象的存在,来保证一致性或者节约内存等。这时,就用到了单例模式。
单例模式的做法是,将类的构造方法私有化,不对外开放。在类的内部定义一个该类的静态实例成员。通过一个静态方法对外提供该成员。
但这里就有一些问题了,这个实例化对象什么时候创建?
通常有两种方法:饿汉式/懒汉式
- 饿汉式:在定义时创建 instance = new A();
- 懒汉式:在getInstance时,判断,如果没有实例化,先实例化再返回。称为延迟加载。
- if( instance == null ) { instance = new A(); } return instance;
- 饿汉式在类初始化时就创建了instance实例,无法做到延迟加载。无论后面是否使用,都占用着内存。
- 懒汉模式在多线程场景下,会创建多个实例,或者因为重排序在没有实例化完成时,却返回了该对象的引用,导致使用时出错。
private static Something instance = null;public Something getInstance() { if (instance == null) { synchronized (this) { if (instance == null) instance = new Something(); } } return instance;}
这段代码还是会因为重排序,导致new的对象没有初始化完成,却已经将引用赋给了instance。其他线程拿到一个没有初始化完成的实例,导致使用出错。在1.5的jvm后,volatile关键字可以解决这个问题。如果将上述代码中的instance用volatile修饰,由于volatile变量的读写操作间存在happens-before关系,因此可以阻止重排序,使其他线程拿到的一定是初始化完成的实例。但是,volatile在拥有如此强大的功能的同时,他的性能开销也有很大程度的上升,已经快达到了同步的级别,所以这种方式虽然没有逻辑上的错误,但仍不是一个最近好的选择。
人类是聪明的动物,总能想到解决为的办法。IODH技术,很好的解决了上面说的所有问题。代码如下:
public class IODHCode {
private static class Gener{private static IODHCode instance = new IODHCode();}public static IODHCode getInstance() {return Gener.instance;}
}
这种技术利用了内部静态类,内部静态类在调用它的时候才进行加载,并且由jvm保证其线程安全性。这样既做到了延迟加载,又在代码层面没有加锁,不影响性能。
优点:
- 提供对唯一实例的控制
- 节约资源
缺点:
- 职责过重,既当工厂,又当产品
- 长时间不用,会被垃圾回收,导致共享状态丢失。(有争议)
1 0
- 单例、单例模式
- 单例模式-多线程单例模式
- 单件模式(单例模式)
- 设计模式------单例模式
- 设计模式------单例模式
- 设计模式-单例模式
- 设计模式 - 单例模式
- 设计模式---单例模式
- 设计模式---单例模式
- PHP模式-单例模式
- 【设计模式】单例模式
- 设计模式-单例模式
- 设计模式----单例模式
- 设计模式--单例模式
- 设计模式-单例模式
- 单例模式(单子模式)
- 设计模式-单例模式
- [设计模式] 单例模式
- VS2013上编译并使用Tesseract3.0.3.中文识别技术
- 建造者模式
- is 与 as
- BLE 速率
- ajax 异步提交数据、文件和跨域提交的实现
- 单例模式
- SpringMVC之controller篇
- 适配器模式
- Java 解析 XML
- 支付宝的支付保卫战
- linux dd 命令 硬盘拷贝 系统快速安装 硬盘系统复制
- 通过ftp采集文件的性能总结
- UICollectionView如果在数据不够一屏时上下滚动
- 桥接模式