在面向對象語言開發中,單例模式作為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的情況。