【線程系列三】線程的等待與喚醒機制


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

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

public final void wait() throws InterruptedException
	當前線程必須擁有此對象監視器。該線程發布對此監視器的所有權並等待,直到其他線程通過調用 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方法不會。
 
         
線程的五態轉換圖:
 
          
        
 
wait()會立刻釋放sycronized(obj)中的obj鎖,以便其他線程可以執行obj.nodify()
但是nodify()不會立刻立刻釋放sycronized(obj)中的obj鎖,
必須要等nodify()所在線程執行完sycronized(obj)塊中的所有代碼才會釋放這把鎖


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM