場景
在學習Mybatis或者Hibernate中,有一個SqlSessionFactory對象。此對象屬於重量級對象,消耗的資源比較大,也只需要存在一個即可。類似的對象還有,線程池、緩存、日誌等。這種情況下,就可以使用單例模式來進行控制對象的創建,確保只存在一個。
餓漢模式
懶漢的的單例模式顧名思義就是,在使用前就已經完成的初始化。
代碼:
public class HungrySingleton {
//類裝載時就完成初始化
private static HungrySingleton hungrySingleton = new HungrySingleton();
//申明私有的構造方法,無法外部通過new初始化對象
private HungrySingleton() {
}
public static HungrySingleton getSingleton() {
System.out.println("獲取單例對象");
return HungrySingleton.hungrySingleton;
}
}
這樣的寫法很簡單,但由於在類裝載時就完成了初始化,可能會造成一定的資源浪費,但是不存在多線程的問題,比較常見。
懶漢模式
餓漢模式是在類裝載的時候就完成了初始化,懶漢模式在被調用的時候才進行初始化,不會造成內存的浪費問題。
代碼:
public class LazySingleton {
private static LazySingleton lazySingleton;
//申明私有的構造方法,無法外部通過new初始化對象
private LazySingleton() {
}
public static LazySingleton getLazySingleton() {
//多線程中,可能出現問題,導致多次初始化
if (lazySingleton == null) {
System.out.println("完成懶漢加載");
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
在多線程中,一個線程準備創建一個對象,這時另一個線程進入if條件判斷中,此時對象還未創建,兩個線程都將創建對象。
懶漢—Version2.0
public class LazySingleton {
private static LazySingleton lazySingleton;
//申明私有的構造方法,無法外部通過new初始化對象
private LazySingleton() {
}
//同步
public static synchronized LazySingleton getLazySingleton() {
if (lazySingleton == null) {
System.out.println("完成懶漢加載");
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
一整個方法加上synchronized 進行同步,對性能而言會存在很大的問題,再進一步改進。
懶漢—Version3.0
public class LazySingleton {
private static LazySingleton lazySingleton;
//申明私有的構造方法,無法外部通過new初始化對象
private LazySingleton() {
}
//同步
public static synchronized LazySingleton getLazySingleton() {
if (lazySingleton == null) {
synchronized (LazySingleton.class) {
if (lazySingleton == null) {
System.out.println("完成懶漢加載");
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
}
需要對對象進行雙重檢查才能保證在多線程下,不會創建多個對象。