單例設計模式面試
Singleton是一種建立型模式,指某個類採用Singleton模式,則在這個類被建立後,只可能產生一個實例供外部訪問,而且提供一個全局的訪問點。設計模式
核心知識點以下:安全
(1) 將採用單例設計模式的類的構造方法私有化(採用private修飾)。多線程
(2) 在其內部產生該類的實例化對象,並將其封裝成private static類型。併發
(3) 定義一個靜態方法返回該類的實例。性能
/** * 方法一 * 單例模式的實現:餓漢式,線程安全 但效率比較低 */ public class SingletonTest {
// 定義一個私有的構造方法 private SingletonTest() { }
// 將自身的實例對象設置爲一個屬性,並加上Static和final修飾符 private static final SingletonTest instance = new SingletonTest();
// 靜態方法返回該類的實例 public static SingletonTest getInstancei() { return instance; } }
方法一就是傳說的中的餓漢模式
優勢是:寫起來比較簡單,並且不存在多線程同步問題,避免了synchronized所形成的性能問題;
缺點是:當類SingletonTest被加載的時候,會初始化static的instance,靜態變量被建立並分配內存空間,從這之後,這個static的instance對象便一直佔着這段內存(即使你尚未用到這個實例),當類被卸載時,靜態變量被摧毀,並釋放所佔有的內存,所以在某些特定條件下會耗費內存。優化
/** *方法二 * 單例模式的實現:飽漢式,非線程安全 * */ public class SingletonTest {
// 定義私有構造方法(防止經過 new SingletonTest()去實例化) private SingletonTest() { }
// 定義一個SingletonTest類型的變量(不初始化,注意這裏沒有使用final關鍵字) private static SingletonTest instance;
// 定義一個靜態的方法(調用時再初始化SingletonTest,可是多線程訪問時,可能形成重複初始化問題) public static SingletonTest getInstance() { if (instance == null) instance = new SingletonTest(); return instance; } }
方法二就是傳說的中的飽漢模式
優勢是:寫起來比較簡單,當類SingletonTest被加載的時候,靜態變量static的instance未被建立並分配內存空間,當getInstance方法第一次被調用時,初始化instance變量,並分配內存,所以在某些特定條件下會節約了內存;
缺點是:併發環境下極可能出現多個SingletonTest實例。spa
/** *方法三 * 單例模式的實現:飽漢式,線程安全簡單實現 * */ public class SingletonTest {
// 定義私有構造方法(防止經過 new SingletonTest()去實例化) private SingletonTest() { }
// 定義一個SingletonTest類型的變量(不初始化,注意這裏沒有使用final關鍵字) private static SingletonTest instance;
// 定義一個靜態的方法(調用時再初始化SingletonTest,使用synchronized 避免多線程訪問時,可能形成重的復初始化問題) public static synchronized SingletonTest getInstance() { if (instance == null) instance = new SingletonTest(); return instance; } }
方法三爲方法二的簡單優化
優勢是:使用synchronized關鍵字避免多線程訪問時,出現多個SingletonTest實例。
缺點是:同步方法頻繁調用時,效率略低。線程
/** * 方法四 * 單例模式最優方案 * 線程安全 而且效率高 * */ public class SingletonTest {
// 定義一個私有構造方法 private SingletonTest() {
} //定義一個靜態私有變量(不初始化,不使用final關鍵字,使用volatile保證了多線程訪問時instance變量的可見性,避免了instance初始化時其餘變量屬性還沒賦值完時,被另外線程調用) private static volatile SingletonTest instance;
//定義一個共有的靜態方法,返回該類型實例 public static SingletonTest getIstance() {
// 對象實例化時與否判斷(不使用同步代碼塊,instance不等於null時,直接返回對象,提升運行效率) if (instance == null) {
//同步代碼塊(對象未初始化時,使用同步代碼塊,保證多線程訪問時對象在第一次建立後,再也不重複被建立) synchronized (SingletonTest.class) {
//未初始化,則初始instance變量 if (instance == null) { instance = new SingletonTest(); } } } return instance; } }
方法四爲單例模式的最佳實現。內存佔用地,效率高,線程安全,多線程操做原子性。設計
(事實上,能夠經過Java反射機制來實例化private類型的構造方法,此時基本上會使全部的Java單例實現失效。本帖不討論反射狀況下問題,默認無反射,也是常見的面試已經應用場景)