1. 程式人生 > >執行緒的等待與喚醒機制

執行緒的等待與喚醒機制

為了更高效的處理一些時間片短任務量大的任務,我們可能會經常用到多執行緒。但是多執行緒的環境下,很容易出現執行緒併發問題,執行緒死鎖就是很常見的一種併發問題。為了避免此類問題,我們會用到執行緒間的通訊,而等待喚醒機制,就是執行緒間通訊的一種形式。

等待喚醒機制用到的方法主要有:

當前執行緒必須擁有此物件監視器。該執行緒釋出對此監視器的所有權並等待,直到其他執行緒通過呼叫 notify 方法,或 notifyAll 方法通知在此物件的監視器上等待的執行緒醒來。然後該執行緒將等到重新獲得對監視器的所有權後才能繼續執行。
wait()還有另外兩個過載的方法 :
wait(long timeout)、 wait(long timeout,int nanos)
public final void notify()
喚醒在此物件監視器上等待的單個執行緒。如果所有執行緒都在此物件上等待,則會選擇喚醒其中一個執行緒。選擇是任意性的,並在對實現做出決定時發生。執行緒通過呼叫其中一個 wait 方法,在物件的監視器上等待。直到當前執行緒放棄此物件上的鎖定,才能繼續執行被喚醒的執行緒。被喚醒的執行緒將以常規方式與在該物件上主動同步的其他所有執行緒進行競爭;
例如,喚醒的執行緒在作為鎖定此物件的下一個執行緒方面沒有可靠的特權或劣。此方法只應由作為此物件監視器的所有者的執行緒來呼叫。通過以下三種方法之一,執行緒可以成為此物件監視器的所有者:
1、通過執行此物件的同步例項方法。
2、通過執行在此物件上進行同步的 synchronized 語句的正文。
3、對於 Class 型別的物件,可以通過執行該類的同步靜態方法。一次只能有一個執行緒擁有物件的監視器。
public final void notifyAll():
喚醒在此物件監視器上等待的所有執行緒。執行緒通過呼叫其中一個 wait 方法,在物件的監視器上等待。直到當前執行緒放棄此物件上的鎖定,才能繼續執行被喚醒的執行緒。被喚醒的執行緒將以常規方式與在該物件上主動同步的其他所有執行緒進行競爭;
例如,喚醒的執行緒在作為鎖定此物件的下一個執行緒方面沒有可靠的特權或劣勢。此方法只應由作為此物件監視器的所有者的執行緒來呼叫。
需要注意:
1、執行緒用到的鎖物件可以是任意物件,這點從wait方法和notify方法可以看出來,因為它們是Object類的方法,而Object類是所有類的父類。
2、上文中所提到的“監視器”即指“鎖物件”。
3、wait方法被呼叫時,執行緒進入阻塞狀態,會釋放所佔用的資源,釋放cpu執行權,丟擲InterruptedException,這幾點與sleep方法是相同的。但是與之不同的地方時,wati方法還會釋放鎖,而sleep方法不會。
執行緒的五態轉換圖: