【Object類中的wait()方法和notify()方法】oop
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類中。