多執行緒 等待 通知模式輔助類Condition

2022-09-20 11:48:11 字數 3631 閱讀 3139

在j**a中,對於任意乙個j**a物件,它都擁有一組定義在j**a.lang.object上監視器方法,包括wait(),wait(long timeout),notify(),notifyall(),這些方法配合synchronized關鍵字一起使用可以實現等待/通知模式。

同樣,condition介面也提供了類似object監視器的方法,通過與lock配合來實現等待/通知模式。

為了更好的了解condition的特性,我們來對比一下兩者的使用方式以及功能特性:

對比項

object監視器

condition

前置條件

獲取物件的鎖

呼叫lock.lock獲取鎖,呼叫lock.newcondition獲取condition物件

呼叫方式

直接呼叫,比如object.notify()

直接呼叫,比如condition.await()

等待佇列的個數

乙個多個

當前執行緒釋放鎖進入等待狀態

支援支援

當前執行緒釋放鎖進入等待狀態,在等待狀態中不斷響中斷

不支援支援

當前執行緒釋放鎖並進入超時等待狀態

支援支援

當前執行緒釋放鎖並進入等待狀態直到將來的某個時間

不支援支援

喚醒等待佇列中的乙個執行緒

支援支援

喚醒等待佇列中的全部執行緒

支援支援

實現乙個簡單的有界佇列,隊列為空時,佇列的刪除操作將會阻塞直到佇列中有新的元素,佇列已滿時,佇列的插入操作將會阻塞直到佇列出現空位。

不難看出,condition的使用方式是比較簡單的,需要注意的是使用condition的等待/通知需要提前獲取到與condition物件關聯的鎖,condition物件由lock物件建立。

以上述示例中的add(t object)為例,詳細描述一下condition等待/通知的整個過程:

總的來說,condition的等待/通知使用方式大體上跟經典的object監視器上的等待/通知是非常類似的。

condition提供以下介面以供實現:

void await() throws interruptedexception

當前執行緒進入等待狀態,直到被通知(signal)或者被中斷時,當前執行緒進入執行狀態,從await()返回;

void awaituninterruptibly()

當前執行緒進入等待狀態,直到被通知,對中斷不做響應;

long awaitnanos(long nanostimeout) throws interruptedexception

在介面1的返回條件基礎上增加了超時響應,返回值表示當前剩餘的時間,如果在nanostimeout之前被喚醒,返回值 = nanostimeout - 實際消耗的時間,返回值 <= 0表示超時;

boolean await(long time, timeunit unit) throws interruptedexception

同樣是在介面1的返回條件基礎上增加了超時響應,與介面3不同的是:

可以自定義超時時間單位;

返回值返回true/false,在time之前被喚醒,返回true,超時返回false。

boolean awaituntil(date deadline) throws interruptedexception

當前執行緒進入等待狀態直到將來的指定時間被通知,如果沒有到指定時間被通知返回true,否則,到達指定時間,返回false;

void signal()

喚醒乙個等待在condition上的執行緒;

void signalall()

喚醒等待在condition上所有的執行緒。

conditionobject是condition在j**a併發中的具體的實現,它是aqs的內部類。因為condition相關操作都需要獲取鎖,所以作為aqs的內部類也比較合理。接下來就以conditionobject的等待佇列、等待、通知為切入點分析conditionobject的具體實現。

conditionobject的等待佇列是乙個fifo佇列,佇列的每個節點都是等待在condition物件上的執行緒的引用,在呼叫condition的await()方法之後,執行緒釋放鎖,構造成相應的節點進入等待佇列等待。其中節點的定義復用aqs的node定義。

插入節點只需要將原有尾節點的nextwaiter指向當前節點,並且更新尾節點。更新節點並沒有像aqs更新同步佇列使用cas是因為呼叫await()方法的執行緒必定是獲取了鎖的執行緒,鎖保證了操作的執行緒安全。

注:aqs實質上擁有乙個同步佇列和多個等待佇列,具體對應關係如下圖所示:

呼叫condition的await開頭的系列方法,當前執行緒進入等待佇列等待,那麼condition的等待實質是await系列方法的具體實現。

具體執行流程如下:

其他以await開頭的方法具體實現與await基本一致,只是在它的基礎上增加了超時限制,不管有沒有被喚醒,到達指定時間,等待結束,從await返回。整個await系列方法將執行緒加入等待佇列的流程可以總結為下圖:

呼叫condition的signal()方法將會喚醒再等待佇列中的首節點,該節點也是到目前為止等待時間最長的節點。

1、signal實現

可以看出,dosignal方法是整個signal方法實現的核心,它完成了將執行緒從喚醒的所有操作。

2、dosignal實現

整個dosignal完成了這兩個操作:呼叫transferforsignal將節點從等待佇列移動到同步佇列,並且,將該節點從等待佇列刪除。

3、transferforsignal實現

condition的signalall()方法,將等待佇列中的所有節點全部喚醒,相當於將等待佇列中的每乙個節點都執行一次signal()。整個signal系列方法將執行緒從等待佇列移動到同步佇列可以總結為下圖:

多執行緒同步輔助類

同步輔助類之訊號量 允許指定共享資源數量,可以允許指定數量的執行緒同時訪問資源 與同步的區別在於,同步時,一次只能乙個執行緒訪問資源 author administrator public class semaphoredemo catch interruptedexception e start ...

03 Java多執行緒 執行緒等待通知機制

三 執行緒等待通知 四 參考 如果等待時長為t,當前時間為now,那麼now t以後超時 long overtime now t long remain t while result不滿足 remian 0 return result shop類模擬商店,初始狀態玩具是nothing,執行緒等待玩具...

多執行緒傳輸檔案輔助類

基類 using system using system.collections.generic using system.text using system.io namespace socketserver set 下一包 public intnextbag 總包數 public intallb...