天天看點

Object類中的wait()方法和notify()方法

【Object類中的wait()方法和notify()方法】

	wait():
		public final void wait(long timeout) throws InterruptedException
		參數:等待的時間,可選,不填則預設為0。
		說明:
			1>使線程主動釋放對象鎖,并進入等待狀态,直到它被其他線程通過notify()或notifyAll喚醒或者超過指定的等待時間。
			2>在調用wait方法前,線程必須獲得該對象的對象鎖,即:隻能在同步方法或同步代碼塊中調用wait方法,如果目前線程不是鎖的持有者,将抛出一個IllegalMonitorStateException異常(是RuntimeException的子類,故不需要捕獲)。
			3>wait方法執行完成後,該線程立即釋放持有的對象鎖(注:不是等到退出synchronized代碼塊後才釋放)。
			4>this method should always be used in a loop:
			
				synchronized (obj) {
					// 不滿足條件時等待。	
					while (condition does not hold) {	
						obj.wait();						// 注:一般會有其它的線程當條件滿足後調用notify方法
					}		
					// 滿足條件時執行execute方法。
					execute();					 		// 注:使用while循環保證了這行代碼始終是在滿足條件下被執行的!	
				}
				
				舉例:
					階段1)A線程執行該代碼塊時,發現不滿足條件condition,則A線程進入等待狀态,并釋放對象鎖,
					階段2)B線程執行某些代碼後,滿足了條件condition,然後調用notify()方法并釋放了對象鎖,
					階段3)如果此時C線程獲得了該對象鎖,并執行了某些代碼導緻又不滿足條件condition了,當C線程釋放該對象鎖後,
					階段4)A線程才獲得了該對象鎖,并執行wait()方法後面的代碼。如果不使用while循環,而是使用if語句來判斷(如下),則會導緻execute()方法在不滿足條件的情況下被執行了!
						synchronized (obj) {
							if (condition does not hold) {	
								obj.wait();
							}
							execute();
						}
				解析:
					執行execute方法的情況:
						1)執行代碼塊時,條件已滿足,則不會調用wait方法,直接執行execute方法。
						2)執行代碼塊時,條件不滿足,則調用wait方法,等到被喚醒後(注:被喚醒後條件可能發生變化),再去執行execute方法。
					使用while循環:保證了在調用wait方法前(階段1)和在被喚醒後(階段4)都去檢查條件是否滿足,如果滿足則執行excute方法,如果不滿足則繼續等待。
					使用if語句:隻保證了在調用wait方法前(階段1)去檢查條件是否滿足,并沒有線上程被喚醒後去檢查是否滿足條件。如果發生了階段3的情況,則execute方法将在不滿足條件的情況下執行了。
	
	
	notify():
		public final void notify()
		說明:
			1>随機選擇一個在該對象上調用wait方法的線程,賦予其對象鎖,解除其阻塞狀态。
			2>在執行notify()方法後,目前線程不會馬上釋放該對象鎖,要等到執行notify()方法的線程退出synchronized方法或synchronized代碼塊後,目前線程才會釋放鎖,此時wait狀态的線程才可以擷取該對象鎖,并繼續執行synchronized代碼塊中wait()方法後面的代碼。
		
		
	notifyAll():
		public final void notifyAll()
		說明:喚醒在該對象上調用wait方法等待的所有線程。
		

	說明:wait()、notify()、notifyAll()這三個方法:
		1)在調用方法前,線程必須獲得該對象的對象鎖,如果目前線程不是鎖的持有者,方法将抛出一個IllegalMonitorStateException異常(是RuntimeException的子類,故不需要捕獲)。
		2)隻能在非靜态同步方法或非靜态同步代碼塊内調用,而且必須由鎖對象來調用方法:
			1>這3個方法都是非靜态方法,且這3個方法必須由鎖對象調用,是以我們不能在靜态同步方法和靜态代碼塊中調用(靜态同步方法的鎖是類的Class鎖)。
			2>synchronized修飾的非靜态方法:因為this就是鎖對象,是以可以在同步方法中調用這三個方法(可以将this省略)。
			3>synchronized修飾的非靜态同步代碼塊:必須使用鎖對象來調用這三個方法。
		3)由于wait,notify和notifyAll都是鎖級别的操作,而鎖屬于對象,故把他們定義在Object類中,而不是定義在Thread類中。
		

		

	
	
           

繼續閱讀