上篇我们学习了最简单的单例模式,但在有些应用下,我们希望只有在使用到该类的时候才去创建实例,而不是在类加载的时候。
下面我们看到的单例模式实现在多线程并发情况下是不安全的。
public class SingletonUnSafe {
private static SingletonUnSafe instance;
private SingletonUnSafe() {
}
public static SingletonUnSafe getInstance() {
if (null == instance) {
instance = new SingletonUnSafe();
}
return instance;
}
}
多线程并发情况下,程序在执行
if (null == instance)
{
instance = new SingletonUnSafe();
}
由于CPU对多线程执行策略,会产生多个实例。为了避免这样的问题,我们可以将
getInstance()方法声明为
synchronized
public class SingletonUnSafe {
private static SingletonUnSafe instance;
private SingletonUnSafe() {
}
public static synchronized SingletonUnSafe getInstance() {
if (null == instance) {
instance = new SingletonUnSafe();
}
return instance;
}
}
对整个方法声明
为
synchronized,在多线程并发情况下对性能会有影响,所以我们使用synchronized代码块来实现
public class SingletonThreadSafe {
private volatile static SingletonThreadSafe instance;
private SingletonThreadSafe() {
}
public static SingletonThreadSafe getInstance() {
if (null == instance) {
synchronized (SingletonThreadSafe.class) {
if (null == instance) {
instance = new SingletonThreadSafe();
}
}
}
return instance;
}
}
大家会注意到代码
if (null == instance){
synchronized (SingletonThreadSafe.class) {
if (null == instance) {
instance = new SingletonThreadSafe();
}
}
}
这里的双重判断可以使程序在创建了实例后,避免每次都执行
synchronized代码块。
现在我们已经完成了线程安全的单例模式。