1. 程式人生 > >第六章單例模式與多執行緒——立即載入“餓漢模式”與延遲載入“懶漢模式”

第六章單例模式與多執行緒——立即載入“餓漢模式”與延遲載入“懶漢模式”

立即載入就是使用類的時候已經將物件建立完畢了,也稱為“餓漢模式”

package test01;

public class MyObject {
//	建立物件
	private static MyObject object = new MyObject();
	private MyObject(){
		
	}
	//用來返回例項物件,因為此方法沒有同步,因此出現非執行緒安全問題
	public static MyObject getInstance() {
		return object;
	}
}

延遲載入是在呼叫get方法時例項才被建立,也稱為“懶漢模式”

延遲載入模式缺點:在多執行緒環境中,延遲載入模式根本不能實現保持單例的狀態

package test02;
//懶漢模式的缺點
//2018-9-27by tiffany
public class MyObject {
	private static MyObject object;
	private MyObject() {
		
	}
//	在get方法中建立物件,不能實現保持單例的狀態
	public static MyObject getInstance() {
	try {	
		if(object != null) {
	}else {
			Thread.sleep(2000);
			object = new MyObject();
		} 
	}catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return object;
}
}

建立三個執行緒並進行呼叫,輸出結果:

延遲載入模式的解決方案:

(1)宣告synchronized關鍵字

package test02;
//使用synchronized關鍵字解決延遲載入模式非單例問題
//2018-09-27 by Tiffany
public class MyObject01 {
	private static MyObject01 object;
	private MyObject01() {
		
	}
	synchronized public static MyObject01 getInstance() {
		if(object != null) {
			
		}else {
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			object = new MyObject01();
		}
		return object;
	}
}

輸出結果是同一個雜湊值,但此種方法執行效率十分低下,嘗試考慮使用同步程式碼塊

(2)嘗試同步程式碼塊

package test02;
//使用同步程式碼塊解決延遲載入模式非單例情況
//2017-09-27 by Tiffany
public class MyObject02 {
	private static MyObject02 object;
	private MyObject02() {
		
	}
	public static MyObject02 getInstance() {
		synchronized(MyObject02.class) {
		if(object != null) {
			
		}else {
			try {
				Thread.sleep(2000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			object = new MyObject02();
		}
		}
		return object;
	}
}

此方法執行效率依然很低

(3)針對某些重要的程式碼進行單獨的同步

同步程式碼塊可以針對某些重要的程式碼進行單獨的同步,而其他的程式碼則不需要同步,這樣雖然效率提高了,但是在多執行緒的情況下依然無法解決同一個物件的問題

(4)使用DCL雙檢查鎖機制(用來實現多執行緒環境下的延遲載入單例設計模式)