多線程之間經常需要協同工作,最常見的方式是使用guarded blocks,它循環檢查一個條件(通常初始值為true),直到條件發生變化才跳出循環繼續執行。在使用guarded blocks時有以下幾個步驟需要注意:
假設guardedjoy()方法必須要等待另一線程為共享變量joy設值才能繼續執行。那麼理論上可以用一個簡單的條件循環來實作,但在等待過程中guardedjoy方法不停的檢查循環條件實際上是一種資源浪費。
<code></code>更加高效的方法是調用object.wait将目前線程挂起,直到有另一線程發起事件通知(盡管通知的事件不一定是目前線程等待的事件)。
注意:一定要在循環裡面調用wait方法,不要想當然的認為線程喚醒後循環條件一定發生了改變。
和其他可以暫停線程執行的方法一樣,wait方法會抛出interruptedexception,在上面的例子中,因為我們關心的是joy的值,是以忽略了interruptedexception。
為什麼guardedjoy是synchronized方法?假設d是用來調用wait的對象,當一個線程調用d.wait,它必須要擁有d的内部鎖(否則會抛出異常),獲得d的内部鎖的最簡單方法是在一個synchronized方法裡面調用wait。
當第二個線程釋放這個該鎖後,第一個線程再次請求該鎖,從wait方法傳回并繼續執行。
注意:還有另外一個通知方法,notify(),它隻會喚醒一個線程。但由于它并不允許指定哪一個線程被喚醒,是以一般隻在大規模并發應用(即系統有大量相似任務的線程)中使用。因為對于大規模并發應用,我們其實并不關心哪一個線程被喚醒。
現在我們使用guarded blocks建立一個生産者/消費者應用。這類應用需要在兩個線程之間共享資料:生産者生産資料,消費者使用資料。兩個線程通過共享對象通信。在這裡,線程協同工作的關鍵是:生産者釋出資料之前,消費者不能夠去讀取資料;消費者沒有讀取舊資料前,生産者不能釋出新資料。