多语言展示
当前在线:112今日阅读:22今日分享:22

singleton模式(单例模式)

本经验介绍在某些语言下的单例模式的实现方式。假定用户了解了单例模式基本概念。
工具/原料

eclipse

Java语言
1

在不考虑线程安全的情况下,经典的单例模式实现,如图:构造函数私有化是为了在外部不能够创建实例,只能该类的内部构造实例。

2

在考虑线程安全的情况下,可以有多种实现方式,每种实现方式的效率是不一样的。在后续的几个步骤中介绍在考虑线程安全的情况下的单例模式的实现。线程安全的关键点是创建实例和赋值的过程,可能有多个线程执行了创建,然后进行了赋值。所以单例模式的线程安全都是保证创建实例并赋值的过程是串行的,即只能有一个线程可以执行。

3

最简单的方式,就是在获取单例的函数上,加上synchronized关键字,这种实现方式的效率是最低的。如图:

4

在函数上用synchronized关键字范围大了。实际上,只需要在创建实例的过程保证只能一个线程可以执行就可以了。如图的例子:例子是用了双重检查(double-checked locking)。在发现未创建实例时,用synchronized保护创建实例的过程。变量使用了volatile关键字,主要是为了防止优化行为导致数据不同步。比如:假设线程A的singleton缓存在寄存器,线程B执行了创建并赋值,此时线程A的singleton并不会刷新。

5

在Java语言说明文档(Java Language Specification)的描述中,说类的初始化过程(class initialization)是串行的,即只能单个线程执行。那么就可以利用这一点来保证单例模式的线程安全。这种是效率最高的。接下来介绍基于语言特性的线程安全单例模式的例子。

6

直接在类成员中创建,如图:这种方式会在类第一次调用的时候初始化,那就不一定是获取单例的函数的调用,比如调用output时,也会初始化成员变量。

7

居于上一个例子可能存在的问题,采用嵌套类的方式,就能保证在调用获取单例的函数时,才创建单例。如图:

注意事项

参考了Wiki。

推荐信息