天天看點

J2SE線程之wait/notify

知識預備

在Java中,每個對象都有個對象鎖标志(Object lock flag)與之想關聯,當一個線程A調用對象的一段synchronized代碼時,它首先要擷取與這個對象關聯的對象鎖标志,然後執行相應的代碼,執行結束後,把這個對象鎖标志傳回給對象;

是以,線上程A執行 synchronized代碼期間,如果另一個線程B也要執行同一對象的一段synchronized代碼時(不一定與線程A執行的相同),它将 要等到線程A執行完後,才能繼續。

wait()和notify()

這兩個方法不屬于Thread 類,而是屬于最底層的object基礎類的。

也就是說不光是Thread,每個對象都有notify和wait的功能,為什麼?因為他們是用來操縱鎖的, 而每個對象都有鎖,鎖是每個對象的基礎,既然鎖是基礎的,那麼操縱鎖的方法當然也是最基礎了。

Think In Java

"wait()允許我們将線程置入"睡眠"狀态,同時又"積極"地等待條件發生改變.而且隻有在一個notify()或notifyAll()發生變化的時候,線程才會被喚醒,并檢查條件是否有變."

Detail

"wait()允許我們将線程置入"睡眠"狀态",也就是說,wait也是讓目前線程阻塞的,這一點和sleep或者suspend是相同的.那和sleep,suspend有什麼差別呢?

差別在于:

"(wait)同時又"積極"地等待條件發生改變",這一點很關鍵,sleep和suspend無法做到.

因為我們有時候需要通過同步(synchronized)的幫助來防止線程之間的沖突,而一旦使用同步,就要鎖定對象,也就是擷取對象鎖,其它要使用該對象鎖的線程都隻能排隊等着, 等到同步方法或者同步塊裡的程式全部運作完才有機會.在同步方法和同步塊中,無論sleep()還是suspend()都不可能自己被調用的時候解除鎖定,他們都霸占着正在使用的對象鎖不放.

而wait卻可以,它可以讓同步方法或者同步塊暫時放棄對象鎖,而将它暫時讓給其它需要對象鎖的人(這裡應該是程式塊,或線程)用。

這意味着可在執行wait()期間調用線程對象中的其他同步方法!在其它情況下(sleep啊,suspend啊),這是不可能的.

但是注意我前面說的,隻是暫時放棄對象鎖,暫時給其它線程使用,我wait所在的線程還是要把這個對象鎖收回來的呀.

wait什麼?就是wait别人用完了還給我啊!

好,那怎麼把對象鎖收回來呢?

第一種方法,限定借出去的時間.在wait()中設定參數,比如wait(1000),以毫秒為機關,就表明我隻借出去1秒中,一秒鐘之後,我自動收回.

第二種方法,讓借出去的人通知我,他用完了,要還給我了.這時,我馬上就收回來.哎,假如我設了1小時之後收回,别人隻用了半小時就完了,那怎麼辦呢?*!當然用完了就收回了,還管我設的是多長時間啊.

那麼别人怎麼通知我呢?

相信大家都可以想到了,notify(),這就是最後一句話"而且隻有在一個notify()或notifyAll()發生變化的時候,線程才會被喚醒"的意思了.

是以,我們可将一個wait()和notify()置入任何同步方法或同步塊内部,無論在那個類裡是否準備進行涉及線程的處理。而且實際上,我們也隻能在同步方法或者同步塊裡面調用wait()和notify().

繼續閱讀