1. 程式人生 > >Java基礎教程:多線程基礎(2)——線程間的通信

Java基礎教程:多線程基礎(2)——線程間的通信

減少 wid png 同時 說明 類的方法 exc 當前 輪詢

Java基礎教程:多線程基礎(2)——線程間的通信

使線程間進行通信後,系統之間的交互性會更強大,在大大提高CPU利用率的同時還會使程序員對各線程任務在處理的過程中進行有效的把控與監督。

線程間的通信

思維導圖

等待中

等待/通知機制

不使用等待/通知機制

  我們可以使用使用sleep()與 whle(true) 死循環來實現多個線程間的通信。

  技術分享圖片

  雖然兩個線程實現了通信,但是線程B必須不斷的通過while語句輪訓機制來檢測某一個條件,這樣會浪費CPU資源。

  如果輪詢間隔較小,更浪費時間間隔。如果輪訓時間間隔較大,有可能會取不到想要得到的數據,所以需要一種機制來實現減少CPU的浪費。

等待/通知機制

  等待/通知機制在生活中比比皆是,比如在就餐時

  技術分享圖片

關於wait

  wait的作用是使當前執行代碼的線程進行等待,wait方法是Object類的方法,該方法用來將當前線程置入“預執行隊列”中,並且在wait()所在的代碼行處停止執行,直到接到通知或被中斷為止。

  在調用wait()之前,線程必須獲得該對象的對象級別鎖,即只能在同步方法或同步塊中調用wait方法

   在執行wait()方法後,當前線程釋放鎖。在從wait返回前,線程與其它線程競爭重新獲得鎖。

   如果調用wait()時沒有持有適當的鎖,則會拋出IllegalMonitorStateException。

關於notify

  方法notify()也要在同步方法或同步塊中調用,即在調用前,線程也必須獲得該對象的對象級別鎖。如果沒有持有對象鎖,則會拋出IllegalMonitorStateException。

  該方法用來通知那些可能等待的該對象的對象鎖的其他線程,如果有多個線程等待,則由線程規劃器隨機挑選出其中一個呈wait狀態的線程,對其發出通知notify,並使它等待獲取該對象的對象鎖。需要說明的是,在執行notify方法後,當前線程不會馬上釋放對象鎖,呈wait狀態的線程也不能馬上獲取該對象鎖,要等待執行notify()方法的線程將程序執行完,也就是說退出synchronized代碼塊後,才能釋放鎖

  第一個獲得該對象鎖的wait線程運行完畢之後,它會釋放掉該對象鎖,此時如果該對象沒有再次使用notify語句,則即便該對象已經空閑,其他wait狀態等待的線程由於沒有得到該對象的通知,還會繼續阻塞在wait狀態,直到這個對象發出一個notify或notifyall。

一句話總結:

  wait使線程停止運行,而notify使停止的線程繼續運行。

技術分享圖片

方法wait鎖釋放和notify鎖不釋放

當方法wait()被執行後,鎖被自動釋放;

執行完notify()方法,鎖不會自動釋放,必須要執行完notify()方法所在的同步synchronized代碼塊後才釋放鎖;

總結

  1. wait()方法可以使調用該方法的線程釋放共享資源的鎖,然後從運行狀態退出,進入等待隊列,直到被再次喚醒。
  2. notify()方法可以隨機喚醒等待隊列中等待同一個共享資源的一個線程,並使該線程退出等待隊列,進入可運行狀態,也就是notify()方法僅通知一個線程。
  3. nofityAll()方法可以使所有正在等待隊列中等待同一個共享資源的全部線程從等待狀態退出,進入可運行狀態。此時,優先級最高的那個線程最先執行,但也有可能是隨機執行,取決於JVM虛擬機的實現。

  技術分享圖片

二.Cond

Java基礎教程:多線程基礎(2)——線程間的通信