设计模式之Singleton
这是一个最简单的模式,但同时也是最容易被误用、滥用的模式,怎样才能用好这个看似简单的模式呢?
在软件系统中,经常有一些类,必须保证它们在系统中只存在一个实例,才能确保逻辑的正确性以及良好的效率。例如,thread pools,caches,dialog boxes,还有Eclipse里面的preferencs设置。
下面是一个最简单的版本:
public class Singleton{
private static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance(){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
这个版本没有考虑到多线程下的执行情况。如果我们有两个线程,都在执行这一段代码,这样就会存在两个实例,怎样避免这个问题?
public class Singleton{
private static Singleton uniqueInstance;
private Singleton(){}
public static synchronized Singleton getInstance(){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}我们可以给这个方法加一个同步,这样就保证了不会有两个线程同时进入这个方法,但是同步的代价太大了。
每个线程也只有在第一次进入这个方法的时候有必要进行同步,当获得了一个实例之后,同步就是多余的了。
还好,我们可以利用JVM的特性,看下一段代码:
public class Singleton{
private static Singleton uniqueInstance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return uniqueInstance;
}
}
JVM已经在线程访问这个方法之前把静态字段初始化了,因此,在你的线程执行getInstance的时候,肯定会返回唯一的一个实例。同样的,.Net的CLR也支持同样的功能,不过,它需要的是一个静态只读字段。
或者,我么可以使用双检查:
public class Singleton{
private volatile static Singleton uniqueInstance;
private Singleton(){}
public static synchronized Singleton getInstance(){
if (uniqueInstance == null){
synchronized (Singleton.class){
if (uniqueInstance == null){
uniqueInstance = new Singleton();
}
}
}
return uniqueInstance;
}
}以上记述了几种单例模式的基本写法,在实际的项目中怎样用,肯定不会是这么简单的,如果诸位有什么心得,还请多多指教啊。


浙公网安备 33010602011771号