一.wait()、notify()和notifyAll()
為了更好的支持多線程之間的協作,JDK提供了三個重要的本地方法
//調用某個對象的wait()方法能讓當前線程阻塞,並且當前線程必須擁有此對象的鎖.
public final void wait() throws InterruptedException {
wait(0);
}
//調用某個對象的notify()方法能夠喚醒一個正在等待這個對象的鎖的線程,如果有多個線程都在等待這個對象的鎖,則只能喚醒其中一個線程
public final native void notify();
//notifyAll()方法能夠喚醒所有正在等待這個對象鎖的線程;
public final native void notifyAll();
如圖:當一個擁有Object鎖的線程調用 wait()方法時,就會使當前線程加入object.wait 等待隊列中,並且釋放當前占用的Object鎖,這樣其他線程就有機會獲取這個Object鎖,獲得Object鎖的線程調用notify()方法,就能在Object.wait 等待隊列中隨機喚醒一個線程(該喚醒是隨機的與加入的順序無關,優先級高的被喚醒概率會高),若果調用notifyAll()方法就喚醒全部的線程。注意:調用notify()方法後並不會立即釋放object鎖,會等待該線程執行完畢後釋放Object鎖。
代碼:
public class WaitTest {
private static Object object=new Object();
public static void main(String[] args) {
Thread thread=new Thread(){
@Override
public void run() {
synchronized (object) {
System.out.println(System.currentTimeMillis()+":"+Thread.currentThread().getName()+"進入啟動");
try {
object.wait();//使當前線程進入等待(進入Object.wait隊列)並釋放對象鎖
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis()+":"+Thread.currentThread().getName()+"線程執行結束");
}
}
};
thread.start();
Thread thread_2=new Thread(){
@Override
public void run() {
synchronized (object) {
System.out.println(System.currentTimeMillis()+":"+Thread.currentThread().getName()+"進入啟動");
try {
object.notify();//隨機在Object.waitd隊列中喚醒一個正在等待該對象鎖的線程
System.out.println(System.currentTimeMillis()+":"+Thread.currentThread().getName()+"喚醒一個等待的線程");
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread_2.start();
}
}
執行結果:
1473306408730:Thread-0進入啟動
1473306408731:Thread-1進入啟動
1473306408731:Thread-1喚醒一個等待的線程
1473306418731:Thread-0線程執行結束
從時間戳中可以看出 Thread-1 在通知Thread-0 繼續執行後,Thread-0 並未立即執行,而是等待Thread-1 釋放Object鎖,在重新獲得Object鎖後,才能繼續執行。(最後兩個時間戳相減剛好是10秒)