几种单例模式的使用及比较

来源:互联网 发布:软件项目总结 编辑:程序博客网 时间:2024/06/18 17:34

单例的使用一般分为三步:

(1)最简单的一种方式

<span style="white-space:pre"></span>private static AudioManager mInstance; //第一步:一个私有静态的类成员变量private AudioManager() {} //第二步:一个私有的构造方法public static AudioManager getInstance() {//第三步:一个public的对外获取实例的方法<span style="white-space:pre"></span>if (mInstance == null) {mInstance = new AudioManager();}return mInstance;}

这种方式只有在单线程的时候工作正常,设想在多线程的情况下,当两个线程同时运行到判断mInstance是否为null的if语句,并且mInstance没有创建时,这时两个线程都回去创建一个实例,此时就不符合单例的要求了。

(2)能在多线程下工作但线率不高的方式

由(1)可知,为了让其能在多线程下正常工作,需要加上一把同步锁,修改如下:

<span style="white-space:pre"></span><span style="font-size:18px;">private static AudioManager mInstance; //第一步:一个私有静态的类成员变量private AudioManager() {} //第二步:一个私有的构造方法public static AudioManager getInstance() {//第三步:一个public的对外获取实例的方法synchronized (AudioManager.class) {<span style="white-space:pre"></span>if (mInstance == null) {<span style="white-space:pre"></span>mInstance = new AudioManager();}}return mInstance;}</span>
通过这种加同步锁的方式,我们可以保证在多线程的环境下只得到一个该类的实例,但我们每次通过getInstance()方法去取实例时,都会试图加上一个同步锁,而加锁是一个非常耗时的操作,在该实例存在时我们就应该尽量避免再去加锁。


(3)推荐使用的方式

<span style="font-size: 18px; "><span style="white-space:pre"></span>/** * 通过单例实现获取本类(AudioManager)对象 */private static AudioManager mInstance; //第一步:一个私有静态的类成员变量private AudioManager() {} //第二步:一个私有的构造方法public static AudioManager getInstance() {//第三步:一个public的对外获取实例的方法if (mInstance == null) {synchronized (AudioManager.class) {if (mInstance == null) {mInstance = new AudioManager();}}}return mInstance;}</span>

如果获取实例时需要给构造方法传入参数,直接在getInstance()里面加入参数即可,如:

<span style="font-size:18px;"><span style="white-space:pre"></span>private String mDir;</span>
<span style="font-size:18px;"><span style="white-space:pre"></span>private static AudioManager mInstance;//第一步:一个私有静态的类成员变量private AudioManager(String dir) {//第二步:一个私有的构造方法mDir = dir;}public static AudioManager getInstance(String dir) {//第三步:一个public的对外获取实例的方法if (mInstance == null) {synchronized (AudioManager.class) {if (mInstance == null) {mInstance = new AudioManager(dir);}}}return mInstance;}</span>


上面的getInstance方法里面通过两次 if 判断,控制只有当mInstance为null即没有创建时,才需要加锁操作。因为只在第一次的时候mInstance为null,因此只有在第一次试图创建实例的时候才需要加锁,相对于第二种方式效率会有很大的提高。







4 0
原创粉丝点击