執行緒間通訊

2021-08-25 11:36:35 字數 3431 閱讀 7601

執行緒間通訊

1.使用wait/notify實現執行緒間通訊

2.生產者/消費者模式實現

3.方法join的使用

4.threadlocal類的使用

等待/通知機制

1.不使用等待/通知機制實現執行緒間通訊

通過while(true)輪詢機制檢查某乙個條件

缺點:這樣乙個死迴圈們非常耗費cpu資源

2.什麼是等待/通知機制

產生資料時間不確定,使用資料時間也不確定。

1.資料還未產生,資料使用者需要等待資料產生

2.資料產生後通知資料使用者,這時資料使用者才知道資料有了,可以使用資料

3.等待/通知機制的實現

方法wait()作用,使當前執行**的執行緒進行等待,將當前執行緒置入到"預執行佇列"中,等待接到通知或被中斷為止

使用wait方法必須獲得物件級別的鎖,所以只能在同步方法或同步**塊中使用

wait方法執行後,當前執行緒放棄鎖,在從wait返回之前,需要和其他執行緒競爭獲取鎖

方法notify()也需要獲得物件級別的鎖,所以也需要在同步方法或同步**塊中使用,如果有多個執行緒等待,執行緒規劃器會隨機

挑選出乙個呈wait等待的執行緒

說明:執行notify()之後,當前執行緒並不會立馬釋放掉鎖,而必須等待執行完synchronized**塊之後,同時wait()執行緒也不會立馬獲得鎖

notifyall()方法可以使所有正在等待佇列中等待同一共享資源的全部執行緒從等待狀態退出,進入可執行狀態,到底哪個執行緒要想執行,取決於

執行緒執行的優先順序,或者jvm的實現情況(隨機的)。

每個鎖物件有兩個佇列,乙個是就緒佇列,乙個是阻塞佇列,就緒佇列儲存了將要獲得鎖的執行緒,阻塞佇列儲存了被阻塞的執行緒,乙個執行緒

被喚醒後之後就會進入到就緒佇列,等待cpu排程,反之,當過乙個執行緒wait之後就會進入阻塞佇列。

4.方法wait()鎖釋放與notify()鎖不釋放

當方法wait()被執行之後,鎖自動釋放,但執行完notify()方法,鎖不會立即釋放

5.當interrupt方法遇到wait方法

當執行緒呈現wait狀態時,呼叫執行緒物件的interrupt方法會出現異常interruptedexception

以上總結:執行完同步**塊會釋放鎖

執行同步**塊異常時,執行緒終止,會釋放鎖

執行wait方法,執行緒會立馬釋放掉鎖,此執行緒物件進入執行緒等待池,等待被喚醒

6.只通知乙個執行緒

呼叫notify()方法一次,只會隨機通知乙個執行緒進行喚醒

7.喚醒所有執行緒

notifyall()

8.方法wait(long)的使用

帶引數的wait(long)方法:等待某一時間是否有現成對鎖進行喚醒,如果超過這個時間,就會自動喚醒1

9.通知過早

如果通知過早,則會打亂程式執行的正常邏輯,就如同先通知了,再等待了,所以就無限等待了

10.等待wait條件發生變化

如果wait等待條件發生變化,則會打亂程式執行的正常邏輯

11.生產者/消費者模式實現

等待/通知模式最經典的案例就是生產者/消費者模式

一生產與一消費:操作值

一對一執行

多生產與多消費:操作值 - 假死

主要原因:雖然**中通過wait和notify通訊,但是並不能保證生產者發出的通知就一定會被消費者執行,也有可能是生產者自己執行,長此下去,所有執行緒都會進入等待狀態

假死的原因就是可能連續喚醒同類

解決方式,通知改為notifyall()

一生產與一消費:操作棧

一生產與多消費:操作棧:解決wait條件改變與加色、

多生產與一消費:操作棧

多生產與多消費:操作棧

12.通過管道進行執行緒之間的通訊(位元組流)

乙個執行緒傳送資料到輸出管道,另乙個執行緒從輸入管道中讀資料

pipedinputstream和pipedoutputstream

pipedreader和pipedwriter

使用inputstream.connect(outputstream)或outputstream.connect(inputstream)的作用使兩個stream之間產生通訊

13.實戰:等待/通知之交叉備份

使用volatile關鍵字共享變數,再結合等待通知實現

方法join的使用

join等待執行緒物件銷毀。主線程建立並啟動子執行緒,子執行緒當中有很多的耗時任務,主線程往往要早於子執行緒提前結束,這時,如果主線程要等子執行緒結束後再結束,就要用到join

1.方法join前的鋪墊

等子執行緒執行完再執行主線程

2.join方法解決

方法join作用是使所屬執行緒物件x正常執行run方法,而使當前執行緒z進行無限期的阻塞,當x執行緒執行完之後再繼續執行z執行緒後面的**

底層用的是wait方法,操作的鎖

join具有使執行緒排隊的作用,有點類似於同步效果

join和synchronized區別:join內部使用wait方法進行等待,而synchronized使用的是物件監視器。

3.方法join與異常

join方法遇到interrupt方法遇到會丟擲異常

例如執行緒x執行,y執行緒呼叫x執行緒,並join x執行緒,當y執行緒執行interrupt方法,y執行緒會丟擲異常,但是x執行緒還是會繼續執行。

4.方法join(long)的使用

方法join(long)中的引數是設定等待的時間

5.join(long)與sleep(loong)區別

join(long)內部使用的是wait(long)方法來實現的,所以具有釋放鎖的特點

thread.sleep(long)不釋放鎖,會持有鎖

6.方法join()後面的**提前執行:出現意外

join必須得到鎖,才會繼續執行

類threadlocal的使用

變數值的共享可以使用public static變數的形式,所有執行緒都是用同乙個public static變數,這個只能存乙個值,並不是物件,list,map、等

實現每個執行緒有自己的共享變數 要用到threadlocal

1.方法get與null

類threadlocal解決的是變數在不同執行緒間的隔離性,也就是不同執行緒擁有自己的值,不同執行緒的值可以放在threadlocal類中進行保護

2.驗證執行緒變數的隔離性

第一次get()返回的是null值

3.解決get()返回null值問題

建立乙個類,繼承自threadlocal,覆蓋他的初始化方法initialvalue(),給他初始化的值

4.再次驗證執行緒變數的隔離性

類inheritablethreadlocal的使用

在子執行緒中取得父執行緒繼承下來的值,如果子執行緒在取值的同時,主線程改變了值,這時候,子執行緒得到的還是舊值

執行緒間通訊

執行緒間通訊 多個執行緒在操作統一資源,但各個執行緒操作的動作不同。資源 class res class input implements runnable public void run else x x 1 2 class output implements runnable public vo...

執行緒間通訊

執行緒間的通訊 在乙個多執行緒的應用程式中,所有執行緒共享程序資源,協同工作。所以,執行緒之間的通訊是編寫多執行緒 應用的必不可少的環節。執行緒之間的通訊包括互斥 同步等,它是多 執行緒設計中最難控制的部分,也是關鍵部分。執行緒間的互斥 1 臨界區 在乙個多執行緒 的應用程式中,可能存在這樣的危險 ...

執行緒間通訊

執行緒間通訊 其實就是多個執行緒在操作同乙個資源 但是操作的動作不同。等待喚醒機制 wait notify 0 notifyall 都使用在同步中,因為要對持有監視器 鎖 的執行緒操作。所以要使用在同步中,因為只有同步才具有鎖 為什麼這些操作執行緒的方法要定義object類中呢?因為這些方法在操作同...