在面向对象语言开发中,单例模式作为23种设计模式中最简单的设计模式,对于我们来说并不陌生,但如何准确并高效的实现单例模式,对于我们来说还是得好好考虑一下。
第一种单例模式:
public class SingletonInstance {
private static SingletonInstance instance;
private SingletonInstance() {
}
public static SingletonInstance getInstance() {
if (instance == null) {
instance = new SingletonInstance();
}
return instance;
}
}
相信大家对这段代码都不陌生,因为我们大多都写过这样的代码。但这种写法会带来很明显的缺陷,当我们在多线程中执行这段代码的时候,如果至少两个线程都执行了getInstance()方法,并且都对instance判断结果为null,这个时候就会产生至少两个SingletonInstance实例。所以从严格意义上讲,这种写法是不正确的。
接下来我们看第二种写法:
public class SingletonInstance {
private static SingletonInstance instance;
private SingletonInstance() {
}
public synchronized static SingletonInstance getInstance() {
if (instance == null) {
instance = new SingletonInstance();
}
return instance;
}
}
这种方法也是我们比较容易想到的,这种写法满足了正确性原则,但频繁的加锁操作也会让我们的代码显得不够高效,如何保证既正确又高效的写法呢?
我们继续来看第三种实现:
public class SingletonInstance {
private static SingletonInstance instance;
private static Object syncObj = new Object();
private SingletonInstance() {
}
public static SingletonInstance getInstance() {
if (instance == null) {
synchronized (syncObj) {
if (instance == null) {
instance = new SingletonInstance();
}
}
}
return instance;
}
}
这种写法是对第二种实现方式的一种改进,即只有在第一次获取SingletonInstance实例时才会进行加锁操作,基本上达到了高效的写法。
接下来我们来看第四种实现方式:
public class SingletonInstance {
private static SingletonInstance instance = new SingletonInstance();
private SingletonInstance() {
}
public static SingletonInstance getInstance() {
return instance;
}
}
比起前面几种实现方式,这种写法算是最高效的了,在jvm类加载器加载SingletonInstance时即已经生成SingletonInstance实例。所以在我们调用getInstance()时也不存在instance为null的情况。