API介紹
//喚醒在此對象監視器上等待的單個線程
void notify()
//喚醒在此對象監視器上等待的所有線程
void notifyAll()
//導致當前的線程等待,直到其他線程調用此對象的notify( ) 方法或 notifyAll( ) 方法
void wait( )
//導致當前的線程等待,直到其他線程調用此對象的notify() 方法或 notifyAll() 方法,或者指定的時間過完。
void wait(long timeout)
//導致當前的線程等待,直到其他線程調用此對象的notify( ) 方法或 notifyAll( ) 方法,或者其他線程打斷了當前線程,或者指定的時間過完。
void wait(long timeout, int nanos)
注意到有個對象監視器的概念
對象監視器是什麼
監視器monitor:可以把它理解爲一種排他性機制,可以用來實現鎖。
同步塊的實現使用了monitor.enter和monitor.exit指令,而同步方法則是依靠方法修飾符上的ACC_SYNCHRONIZED來完成的;其本質是對一個對象的監視器進行獲取
任何線程想要持有Object的鎖,都要嘗試獲取Object的監視器Monitor,如果獲取成功,就持有了該對象的鎖;如果獲取失敗,就進入到同步隊列;當monitor.Exit後,就釋放該對象的鎖,釋放鎖時會喚醒同步隊列等待的線程,他們會嘗試獲取監視器。
鎖住了一個對象,就是獲得對象相關聯的監視器
wait、notify、notifyAll 這三者的使用都必要持有對象的鎖才能執行
Demo
public class Demo {
private static Object object = new Object();
public static void main(String[] args) throws ExecutionException, InterruptedException {
for (int i = 0; i <4 ; i++) {
int finalI = i;
new Thread( ()->{
synchronized (object) {
try {
object.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(finalI);
}
}).start();
}
Thread.sleep(3000);
synchronized (object){
object.notify();
}
}
}
0
結果:輸出0 ,其他線程在等待喚醒。和預想中的一樣,notify只是喚醒其中一個該對象監視器等待的線程
.......
object.notifyAll();
.......
把notify()改成notifyAll()
3
2
1
0
notifyAll:喚醒在此對象監視器上等待的所有線程
參考文章
Java併發-對象監視器
經典解釋監視器和對象鎖