Java設計模式-單例模式(二)單例模式類
阿新 • • 發佈:2018-12-20
餓漢式單例類
餓漢式單例類在載入時單例物件已經被建立。程式碼如下:
/** * 懶漢式單例 * @Author: Rick * @Date: 2018/10/31 17:44 */ public class EagerSingleton { private static EagerSingleton eagerSingleton = new EagerSingleton(); private EagerSingleton(){}; public static EagerSingleton getEagerSingleton(){ return eagerSingleton; } }
懶漢式單例類
與餓漢式單例不一樣的是,懶漢式單例在第一次建立時被例項化。
使用關鍵字synchronized,使用執行緒鎖,實現單例模式,程式碼如下:
** * 懶漢式單例 * @Author: Rick * @Date: 2018/10/31 17:51 */ public class LazySingleton { private static LazySingleton lazySingleton = null; private LazySingleton(){ } //增加了執行緒鎖,執行緒安全,但是增加了系統壓力,使效能降低 synchronized public static LazySingleton getLazySingleton() { if (lazySingleton == null) { lazySingleton = new LazySingleton(); } return lazySingleton; } }
在類上新增關鍵字synchronized,進行單例實現,得到了執行緒安全,但每次都要進行執行緒鎖的判斷,在多執行緒高併發的訪問環境中,導致系統的效能大大降低。getLazySingleton()方法修改為:
public static LazySingleton getLazySingleton(){ if(lazySingleton == null){ synchronized (LazySingleton.class){ lazySingleton = new LazySingleton(); } } return lazySingleton; }
問題:這種方式不能實現單例,在第一個請求到達時,會建立物件,如果此時有第二個呼叫該方法,就會線上程鎖外等待,當第一個請求建立物件完成後,第二個請求處於等待的狀態,會再建立一個物件,所以這種寫法無法實現單例。 使用雙重檢查鎖定實現懶漢式的單例類的完整程式碼如下:
public static LazySingleton getLazySingleton(){
if(lazySingleton == null){
synchronized (LazySingleton.class){
if(lazySingleton == null) {
lazySingleton = new LazySingleton();
}
}
}
return lazySingleton;
}
靜態內部類單例
餓漢式單例不能實現延遲載入,不論將來使用與否都會佔用記憶體;懶漢式單例類執行緒安全控制繁瑣,影響系統性能。可見無論是哪個都存在一些問題。使用靜態內部類來實現單例,可以解決以上問題,程式碼如下:
/**
* 內部類實現單例
* @Author: Rick
* @Date: 2018/10/31 18:25
*/
public class InternalSingleton {
private InternalSingleton(){
}
private static class HolderClass{
/**內部類中進行例項化*/
private final static InternalSingleton INTERNALSINGLETON = new InternalSingleton();
}
public static InternalSingleton getHolderClass() {
return HolderClass.INTERNALSINGLETON;
}
public static void main(String[] args) {
InternalSingleton internalSingleton1,internalSingleton2;
internalSingleton1 = InternalSingleton.getHolderClass();
internalSingleton2 = InternalSingleton.getHolderClass();
System.out.println(internalSingleton1 == internalSingleton2);
}
}