19、設計模式之單例模式-懶漢式
阿新 • • 發佈:2018-12-16
/** * 懶漢式-單例模式 * 多執行緒模式慎用,單例模式會失效,為解決這一問題,可以在靜態方法上加“synchronized”表明鎖住該類本身,同一時間點只有一個執行緒可以訪問該方法 * 該方法雖然可以解決單例失效的問題,但卻非常的消耗資源 */ public class LazySingleton { private static LazySingleton instance = null; private LazySingleton(){ } private synchronized static LazySingleton getInstance(){ if(instance==null){ instance = new LazySingleton(); } return instance; } /** * 與上述方法等效 * @return */ private static LazySingleton getNewInstance(){ synchronized(LazySingleton.class) { if (instance == null) { instance = new LazySingleton(); } } return instance; } }
進一步完善,解決資源佔用過多的問題
/** * 引入雙重鎖概念,完善懶漢式-單例模式 */ public class LazyDoubleCheckSingleton { private volatile static LazyDoubleCheckSingleton instance = null; private LazyDoubleCheckSingleton(){ } public static LazyDoubleCheckSingleton getInstance(){ if(instance==null){ synchronized (LazyDoubleCheckSingleton.class) { if(instance==null) { instance = new LazyDoubleCheckSingleton(); // 這種方式雖然極大地解決了資源佔用多過的問題,但也是存線上程安全性問題 // new 一個物件實際執行了三步操作,如下 // 1、為物件分配記憶體地址 // 2、初始化物件 // 3、將instance指向 新分配的記憶體地址 // 正常情況下,執行順序1->2->3 如此執行,但多執行緒會造成重排序現象1->3->2,如要禁止該現象發生, // 只需要在instance變數宣告上加入一個關鍵字“volatile”, // 多執行緒下 系統會有共享記憶體,volatile會使所有執行緒都能看見該變數的最新狀態, // 在賦值的時候,會將當前行快取資料寫回到共享記憶體,這樣其他執行緒快取的資料就會失效,從而再次向共享記憶體獲取該變數的最新資料 } } } return instance; } }
第二種完善方式,靜態內部類
/** * 完善懶漢式-單例模式 第二種方式:靜態內部類 * 由於靜態內部類被呼叫時,系統會先獲取類物件鎖,這樣一來,多執行緒之間就遮蔽了StaticInnerClassSingleton 類例項化的全過程, * 重排序現象僅對當前執行緒可見且有效 */ public class StaticInnerClassSingleton { private StaticInnerClassSingleton(){ } private static class InnerClass{ private static StaticInnerClassSingleton instance = new StaticInnerClassSingleton(); } public static StaticInnerClassSingleton getInstance(){ return InnerClass.instance; } }
【切記】單例模式,一定要記得建立私有建構函式