等待喚醒機制 Day25

2021-10-01 03:18:34 字數 4035 閱讀 8394

執行緒間通訊

什麼時等待喚醒機制

這是多個執行緒間的一種協作機制。談到執行緒我們經常想到的是執行緒間的競爭(race),比如去爭奪鎖,但這並不是故事的全部,執行緒間也會有協作機制,就是在乙個執行緒進行了規定操作後,就進入等待狀態(wait()), 等待其他執行緒執行完他們的指定**過後再將其喚醒(notify());在有多個執行緒進行等待時, 如果需要,可以使用 notifyall()來喚醒所有的等待執行緒

wait/notify 就是執行緒間的一種協作機制

等待喚醒中的方法

等待喚醒機制就是用於解決執行緒間通訊的問題的,使用到的3個方法的含義如下

1. wait:執行緒不再活動,不再參與排程,進入 wait set 中,因此不會浪費 cpu 資源,也不會去競爭鎖了,這時的執行緒狀態即是waiting。它還要等著別的執行緒執行乙個特別的動作,也即是「通知(notify)」在這個物件上等待的執行緒從wait set 中釋放出來,重新進入到排程佇列(ready queue)中

2. notify:則選取所通知物件的 wait set 中的乙個執行緒釋放;例如,餐館有空位置後,等候就餐最久的顧客最先入座。

3. notifyall:則釋放所通知物件的 wait set 上的全部執行緒。

注意:哪怕只通知了乙個等待的執行緒,被通知執行緒也不能立即恢復執行,因為它當初中斷的地方是在同步塊內,而此刻它已經不再持有鎖,所以需要再次嘗試去獲取鎖(很可能面臨其它執行緒的競爭),獲取鎖成功後才能在當初呼叫 wait 方法之後的地方恢復執行

總結:如果能獲取鎖,執行緒就從 waiting 狀態變成 runnable 狀態; 否則,從 wait set 出來,又進入 entry set,執行緒就從 waiting 狀態又變成 blocked 狀態

呼叫wait和notify方法需要注意的細節

1. wait方法與notify方法必須要由同乙個鎖物件呼叫。因為:對應的鎖物件可以通過notify喚醒使用同乙個鎖對 象呼叫的wait方法後的執行緒。

2. wait方法與notify方法是屬於object類的方法的。因為:鎖物件可以是任意物件,而任意物件的所屬類都是繼 承了object類的。

3. wait方法與notify方法必須要在同步**塊或者是同步函式中使用。因為:必須要通過鎖物件呼叫這2個方法。

等待喚醒機制是「生產者與消費者之間的關係」

就拿生產包子消費包子來說等待喚醒機制如何有效利用資源:

包子鋪執行緒生產包子,吃貨執行緒消費包子。當包子沒有時(包子狀態為false),吃貨執行緒等待,包子鋪執行緒生產包子 (即包子狀態為true),並通知吃貨執行緒(解除吃貨的等待狀態),因為已經有包子了,那麼包子鋪執行緒進入等待狀態。 接下來,吃貨執行緒能否進一步執行則取決於鎖的獲取情況。如果吃貨獲取到鎖,那麼就執行吃包子動作,包子吃完(包 子狀態為false),並通知包子鋪執行緒(解除包子鋪的等待狀態),吃貨執行緒進入等待。包子鋪執行緒能否進一步執行則取決於鎖的獲取情況

包子類

1

package demosummary.waitingandwake;23

/** 4 包子鋪執行緒生產包子,吃貨執行緒消費包子。當包子沒有時(包子狀態為false),吃貨執行緒等待,

5 包子鋪執行緒生產包子 (即包子狀態為true)

6 並通知吃貨執行緒(解除吃貨的等待狀態),因為已經有包子了,那麼包子鋪執行緒進入等待狀態。

7 接下來,吃貨執行緒能否進一步執行則取決於鎖的獲取情況。

8 如果吃貨獲取到鎖,那麼就執行吃包子動作,包子吃完(包 子狀態為false),並通知包子鋪執行緒(解除包子鋪的等待狀態),

9 吃貨執行緒進入等待。包子鋪執行緒能否進一步執行則取決於鎖的獲取情況

10 */

11public

class

baozi

1819

public

baozi

(string pi, string xian,

boolean flag)

2425

public string getpi()

2829

public

void

setpi

(string pi)

3233

public string getxian()

3637

public

void

setxian

(string xian)

4041

public

boolean

isflag()

4445

public

void

setflag

(boolean flag)

4849

@override

50public string tostring()

';56}

57}

包子鋪類

1

package demosummary.waitingandwake;23

public

class

baozipu

extends

thread

1011

@override

12public

void

run(

)catch

(interruptedexception e)23}

24//沒有包子,包子鋪開始做包子

25 system.out.

println

("包子鋪開始做包子");

26//判斷做什麼包子

27if

(count !=0)

else

36 count++;37

//改變包子的狀態為有包子

38 bz.flag =

true

;39 system.out.

println

("包子做好了:"

+bz.

getpi()

+bz.

getxian()

+"包子");

40 system.out.

println

("請等待的顧客可以來拿包子了");

41 bz.

notify()

;42}43

}44}45

}

顧客類

1

package demosummary.waitingandwake;23

public

class

guke

extends

thread

1011

@override

12public

void

run(

)catch

(interruptedexception e)21}

2223 system.out.

println

("顧客已拿到"

+ bz.

getpi()

+ bz.

getxian()

+"包子");

24 bz.flag =

false

;25 bz.

notify()

;26}27

}28}29

}

測試類

1

package demosummary.waitingandwake;23

public

class

test

13}

等待喚醒機制

等待喚醒機制是多執行緒通訊中的概念,首先我們要先了解什麼是執行緒間的通訊 概念 多個執行緒都在處理同乙個資源,但是處理的任務不一樣。此時就需要多執行緒之間進行通訊,保證同一資源的正確性。剖析 通過多執行緒間的通訊的經典例項來進一步了解多執行緒間通訊的概念 經典例項 生產者,消費者 1 首先通過乙個簡...

等待喚醒機制

等待喚醒機制 涉及的方法 wait 將同步中的執行緒處於凍結狀態。釋放了執行權,釋放了資格。同時將執行緒物件儲存到執行緒池中。notify 喚醒執行緒池中某乙個等待執行緒。notifyall 喚醒的是執行緒池中的所有執行緒。注意 1 這些方法都需要定義在同步中。2 因為這些方法必須要標示所屬的鎖。你...

執行緒等待喚醒機制

等待喚醒機制 乙個執行緒在工作時發現某些條件不滿足了,這時可以釋放掉鎖,並暫停工作。目的是讓另乙個執行緒插入進來,進行條件的補給 後進入的執行緒在補足條件後,可以進行 喚醒 將之前所有等待的執行緒喚醒,讓他們繼續工作,然後自己退出。喚醒之後執行的 system.out.println 包子已經做好了...