wait set - 線程的休息室 :
在開始學習 wait, notify 與 notifyAll 之前, 先稍微講一下 wait set. 所有的物件都有一個 wait set. wait set 是一個在執行物件的wait 方法時, 操作停止的線程的集合. 它有點類似線程的休息室, 而且每個物件都會有. 一執行 wait方法時, 現程便會停止操作並進入 wait set 這個休息室. 除非發生下列任一種情況, 否則線程便會永遠留在 wait set 裡. 當發生下列任一情況, 線程便會退出 wait set :
wait 方法 - 把線程放入 wait set :
使用 wait 方法時, 現程便進入 wait set. 假設現在執行下面語句 :
obj.wait();
則目前的線程便會停止操作並進入物件 obj 的 wait set. 這個操作稱為線程在 obj 上的 wait. 如果物件方法還有如下語句 :
wait(); <等同 this.wait();>
則執行該wait() 的線程就會進入 this 的 wait set. 另外能夠執行 wait() 方法的線程, 必須是獲得 this 的鎖定 (規定). 但是當線程進入 wait set時, 同時便會釋放該物件的鎖定. 請參考下圖說明 :


notify 方法 - 從 wait set 拿出線程:
使用notify 方法時, 可以從 wait set 取出一個線程. 假設現在執行如下語句 :
obj.notify();
則會從物件 obj 的 wait set 裡的線程挑出一個, 並喚醒它. 這個過程如下圖說明 :


Ps. 被notify 喚醒的線程並不是在notify 的一瞬間便開始執行. 因為在 notify 的那一刻, 執行notify 的線程還握著鎖定不放, 所以其他線程無法獲得鎖定.
notifyAll 方法 - 從 wait set 拿出所有線程:
notify 只喚醒一個線程, 而notifyAll 則是喚醒所有線程, 這是兩者唯一的差別. 請參照下圖 :

補充說明 :
@. 若沒有被鎖定的線程而去調用 notify, notifyAll 則會拋出 java.lang.IllegalMonitorStateException.
@. 改用 notify 還是 notifyAll 方法?
@. wait, notify 與 notifyAll 是 Object 類別的方法. 不是Thread 固有的方法. 不過因為Object 類別是所有Java 類的父類, 所以 wait, notify 與 notifyAll 也是 Thread 類的方法.
沒有留言:
張貼留言