[设计模式]Singleton - 单例模式

  在写代码的过程中,我们会发现有些对象,其实我们只需要一个实例,比方说:线程池(threadpool)、日志对象等,这时候就需要用到“单例模式”,可以创建唯一的实例。

  简单的单例模式的代码如下:

package com.geekyjane.cnblogs.singleton;

public class Singleton {
	private static Singleton uniqueInstance;

	private Singleton() {
	}

	public static Singleton getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
}

  要满足“只创建一个实例”的条件,就必须禁止其他的类实例化该类,通过自己提供类型实例来控制实例的唯一性。对于有些对象,实例化起来非常耗费资源,而程序在某次执行过程中又有一直没用到它,这样就会造成一种浪费,所以用了lazy instantiaze(延迟实例化),可以在需要的时候再进行实例的创建,从而避免了这样的一种浪费。

  但这也造成了一个多线程的问题,当两个线程AB,当A进入getInstance()方法,检测到uniqueInsatance为空,会通过new Singleton()来创建一个新的对象实例,而这时线程B也进入了该方法,发现uniqueInstance还没有创建出来(为空),也做了uniqueInstance = new Singleton()的操作,我们就会得到两个该对象的实例,这不符合单例模式的要求。

  所以对于多线程来说,我们要考虑线程安全。有三种方法,第一种是拒绝延迟实例化,第二种是同步该刚发,第三种是双重检查加锁(double-checked locking)。

 

package com.geekyjane.cnblogs.singleton;

public class Singleton {
	private static Singleton uniqueInstance = new Singleton();

	private Singleton() {
	}

	public static Singleton getInstance() {
		return uniqueInstance;
	}
}

  对于第一种来说,是最简单快捷的,但是必然是没有延迟实例化来得好,所以不推荐。

package com.geekyjane.cnblogs.singleton;

public class Singleton2 {
	private static Singleton2 uniqueInstance;

	private Singleton2() {
	}

	public static synchronized Singleton2 getInstance() {
		if (uniqueInstance == null) {
			uniqueInstance = new Singleton2();
		}
		return uniqueInstance;
	}
}

  这种方法快捷有效,但是同步会降低性能,而且每一次取得实例时都要同步,这是一种累赘。所以如果你的应用程序要频繁运行getInstance方法,那还是放弃这个选择吧。

package com.geekyjane.cnblogs.singleton;

public class Singleton3 {
	private volatile static Singleton3 uniqueInstance;

	private Singleton3() {
	}

	public static Singleton3 getInstance() {
		if (uniqueInstance == null) {
			synchronized (Singleton3.class) {
				if (uniqueInstance == null) {
					uniqueInstance = new Singleton3();
				}
			}
		}
		return uniqueInstance;
	}
}

  这种方法避免了方法二的缺点,首先检查是否实例已经创建了,如果尚未创建,才进行同步。这样做可以大大减少getInstance的耗时。但是如果你的代码不需要性能上的考虑,这么写似乎又会有些麻烦了。

posted @ 2013-09-15 22:31  geeky_jane  Views(194)  Comments(0Edit  收藏  举报