设计模式学过差不多也有一年了 可到现在只记得零星的几个 看来是有必要复习一遍了。
有些大的对象其实我们只需要一个,比如说:线程池、缓存、日志对,充当打印机、显卡等设备的驱动程序的对象等,这类对象只能有一个实例,如果制造出多个就会产生许多问题。
单件模式确保一个类只能有一个实例,并且提供一个全局的访问点。
public class Singleton {
private static Singleton instance = null;
private Singleton () {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
初看起来这段代码没有一点问题,但如果发生多线程的情况呢?因为多线程的不确定性,就很有可能产生很多个Singleton实例了。再来改善下让它能够适应多线程,如下:
public class Singleton {
private static Singleton instance = null;
private Singleton () {}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
这样做多线程的问题是消除了,但却产生另外的问题:以后每次访问都需要执行同步方法,产生了严重的性能问题。再来改善下多线程,如下:
1、使用急切创建实例,而不使用延迟加载
public class Singleton {
private static Singleton instance = new Singleton();
private Singleton () {}
public static Singleton getInstance() {
return instance;
}
}
现在我们依赖JVM在加载这个类时马上创建此类的单件实例,JVM保证在任何线程访问instance静态变量之前先创建此实例。
2、使用双重检查加锁,在getInstance中减少使用同步
public class Singleton {
// volatile 有效的确保当instance被初始化成实例时,多线程正确的处理instance变量。
private volatile static Singleton instance = null;
private Singleton () {}
public static Singleton getInstance() {
// 如果实例不存在就进入实例块,只有第一次才彻底执行这里的代码。
if (instance == null) {
// 这里有效的阻止了多线程问题的产生
synchronized (Singleton.class) {
// 进入区块后,再检查一次,只有实例为空才创建实例。
if (instance == null) {
instance= new Singleton();
}
}
}
return instance;
}
}