Singleton--单例模式

来源:互联网 发布:java action servlet 编辑:程序博客网 时间:2024/05/16 19:03

[导读]

         单例模式,顾名思义,只有一个实例。很多应用场景下,一个服务,一个组件都会以单例来运行。具体到一个类,一个类只能创建一个对象。

[正文]

1. 单例模式特征

(1). 外界不能显示创建对象,所以构造函数必须为private;

(2). 给外界提供唯一的访问实例的接口,一般名字为:getInstance(), 返回唯一的对象实例;

故单例类的类图可以表示为:


2. 模式实现

模式实现这一块内容相当丰富,尤其是在<<effective java>>里讨论得很精彩。按理说没有必要在这里累赘,就当烂笔头吧。

【实现1】

class Singleton {private static Singleton instance = null;private Singleton(){}public static Singleton getInstance() {if (instance == null) {instance = new Singleton();}return instance;}}
【分析】上述实现为非线程安全,即在多线程环境下,可能产生多个实例,违背了单例的概念语义。


【实现2】

class Singleton {private static Singleton instance = null;private Singleton(){}public synchronized static Singleton getInstance() { // 比上面多了一个synchronized关键字if (instance == null) {instance = new Singleton();}return instance;}}

【分析】上述实现加了一个类级锁,能保证只创建一个实例,但每次取得实例意味着加锁一次,是否有效率提升的空间呢?


【实现3】

class Singleton {private static Singleton instance = null;private Singleton(){}public static Singleton getInstance() {if (instance == null) {synchronized(Singleton.class) {if (instance == null) {instance = new Singleton();}}}return instance;}}

【分析】上述实现就是最经典的double-check locking实现,在多线程环境里不是每个线程都会进入到synchronized同步模块。对于每一个线程,要获取实例都需要做第一层的if判断,依然是效率的问题。当然对比【实现2】,效率已经有了提升。


【实现4】

class Singleton {private static Singleton instance = new Singleton();private Singleton(){}public static Singleton getInstance() {return instance;}}
【分析】上述实现能直接获取单例实例,不用加锁,也不用做任何判断,效率达到了最佳。但是java的静态变量是不管你用不用,只要进程启动,静态变量都会初始化。能优化吗?


【实现5】

class Singleton {private Singleton(){}public static Singleton getInstance() {return SingletonMaker.instance;}private static class SingletonMaker{public static Singleton instance = new Singleton();}}

【分析】增加一个私有静态内部类

(1).静态类不是变量, 所以SingletonMaker类里的成员不会在一开始就初始化

(2). 内部静态类,对外不可见。对内和Singleton是相互可见的。因此由它来创建单例实例,既能满足效率问题,又能避免资源集中在初始阶段去初始化。

这也是lazy load的实现。


ok了。最后一种当然也是最佳实现方式。

原创粉丝点击