什麼是等待/通知機制
舉個栗子:餐廳裏,廚師做好菜之後,通知等待中的服務員就是一個簡單的等待通知機制
wait:
wait方法代碼的作用是使當前執行代碼的線程進入等待,wait方法是Object類的方法,該方法用來將當前線程置入“預執行隊列當中”,並且在wait所在的代碼行處停止執行,直到接到通知或被終端爲止。在wait之前,線程必須獲得該對象的對象級別鎖,即只有在同步方法或同步塊中才能調用wait方法。wait方法執行後,當前線程會立馬釋放鎖。
notify:
notify方法在調用前,也要獲得當前線程的對象級別的鎖,即方法notify也要在同步方法或同步塊中調用。該方法用來通知那些可能等待該對象的對象鎖的其他線程,需要說明的是,在執行notify方法後,當前線程不會立馬釋放該對象鎖,呈wait狀態的線程不能立馬獲得該對象鎖,需要等到notify所在的同步塊執行完纔會釋放該對象鎖。
總結:
wait使線程停止運行,notify使通知停止的線程繼續執行。
notify一次只會隨機喚醒一個線程
看下面的代碼:
public class Service {
public void testMothod(Object lock){
try{
synchronized (lock){
System.out.println(Thread.currentThread().getName()+ " begin wait at " + System.currentTimeMillis());
lock.wait();
System.out.println(Thread.currentThread().getName() + " end wait at " + System.currentTimeMillis());
}
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
public class ThreadA extends Thread {
private Object lock;
public ThreadA(Object object){
this.lock = object;
}
@Override
public void run() {
super.run();
Service serivce = new Service();
serivce.testMothod(lock);
}
}
public class ThreadB extends Thread {
private Object lock;
public ThreadB(Object object){
this.lock = object;
}
@Override
public void run() {
super.run();
Service serivce = new Service();
serivce.testMothod(lock);
}
}
public class ThreadC extends Thread {
private Object lock;
public ThreadC(Object object){
this.lock = object;
}
@Override
public void run() {
super.run();
Service serivce = new Service();
serivce.testMothod(lock);
}
}
public class NotifyOne extends Thread {
private Object lock;
public NotifyOne(Object object){
this.lock = object;
}
@Override
public void run() {
super.run();
synchronized (lock){
lock.notify();
}
}
}
public class Test {
public static void main(String[] args) {
try{
Object object = new Object();
ThreadA threadA = new ThreadA(object);
ThreadB threadB = new ThreadB(object);
ThreadC threadC = new ThreadC(object);
threadA.setName("A");
threadB.setName("B");
threadC.setName("C");
threadA.start();
threadB.start();
threadC.start();
Thread.sleep(1000);
NotifyOne notifyOne = new NotifyOne(object);
notifyOne.start();
} catch (InterruptedException e){
e.printStackTrace();
}
}
}
運行結果:
A begin wait at 1563079593045
B begin wait at 1563079593045
C begin wait at 1563079593045
A end wait at 1563079594044
可以看到 notify方法只喚醒了A線程,那麼喚醒所有線程的方法就是notifyAll嘍
修改NotifyOne類中的notify方法爲notifyAll
public class NotifyOne extends Thread {
private Object lock;
public NotifyOne(Object object){
this.lock = object;
}
@Override
public void run() {
super.run();
synchronized (lock){
lock.notifyAll();
}
}
}
運行結果:
A begin wait at 1563079801021
C begin wait at 1563079801022
B begin wait at 1563079801022
B end wait at 1563079802012
C end wait at 1563079802012
A end wait at 1563079802012
Process finished with exit code 0
可以看到,A B C三個線程都被喚醒了
wait(long)方法介紹
該方法是等待參數值的時間內如果沒有線程對鎖進行喚醒,如果超過這個時間,則自動喚醒。
That's ALL !!!!!!