wait()
調用
wait()
方法后,線程進入等待狀態,wait()
方法不會返回,直到將來某個時刻,線程從等待狀態被其他線程喚醒后,wait()
方法才會返回,然后,繼續執行下一條語句。
wait()
方法的執行機制非常復雜,它不是一個普通的Java方法,而是定義在Object
類的一個native
方法,也就是由JVM的C代碼實現的。
必須在synchronized
塊中才能調用wait()
方法,因為wait()
方法調用時,會釋放線程獲得的鎖,wait()
方法返回后,線程又會重新試圖獲得鎖。
notify()、notifyAll()
this.notifyAll()
將喚醒所有當前正在this
鎖等待的線程,而this.notify()
只會喚醒其中一個(具體哪個依賴操作系統,有一定的隨機性)。這是因為可能有多個線程正在getTask()
方法內部的wait()
中等待,使用notifyAll()
將一次性全部喚醒。通常來說,notifyAll()
更安全。有些時候,如果我們的代碼邏輯考慮不周,用notify()
會導致只喚醒了一個線程,而其他線程可能永遠等待下去醒不過來了。
但是,注意到wait()
方法返回時需要重新獲得this
鎖。假設當前有3個線程被喚醒,喚醒后,首先要等待執行addTask()
的線程結束此方法后,才能釋放this
鎖,隨后,這3個線程中只能有一個獲取到this
鎖,剩下兩個將繼續等待。
實例
class TaskQueue { Queue<String> queue = new LinkedList<>(); public synchronized void addTask(String s) { this.queue.add(s); this.notifyAll(); } public synchronized String getTask() throws InterruptedException { while (queue.isEmpty()) { this.wait(); } return queue.remove(); } }