這兩個方法不併在Thread類中,而是在Object類中.這說明任何對象均可以調用這兩個方法.這兩個方法的方法簽名以下:java
public final void wait() throws InterruptedException; public final native void notify();
當一個對象實例調用了wait()方法後,當前線程就會在這個對象上等待.好比,線程A中,調用了OBJECT.wait()方法,那麼A線程就暫停了執行,轉爲等待狀態,它會一直等待到其餘線程調用了同一對象OBJECT.notify()方法爲止.這時,這個OBJECT對象就成爲兩個線程之間有效的通訊手段.ide
若是一個線程調用了OBJECT.wait(),那麼它就會進入到一個線程等待的隊列當中.這個等待隊列當中,可能會有多個線程,由於系統多個線程都在同時等待某一個對象.當OBJECT.notify()被調用,JVM會從這個等待隊列中,隨機選擇一個線程來喚醒.spa
要注意:上面的過程並非公平的,不會由於你的線程優先級高,或者先進入等待隊列而被優先選擇,是徹底隨機的.線程
除了notify()方法外,Object類還有一個方法是:notifyAll()方法.它和notify()的用法基本一致,但不一樣的是,它會喚醒線程等待隊列中全部等待的線程,而不是隨機選擇一個.code
首先須要強調的是:這三個方法不是隨便就能夠調用的.它們必須包含在對應的synchronized語句塊中,由於不管哪一個方法都要先得到同一個目標的監視器.對象
/** * <p>wait()和notify()方法案例</p> * <p> * wait()和notify()方法必須包含在對應的synchronized語句塊當中, * 不管是wait()仍是notify都須要首先得到目標對象的一個監視器 * </p> * <p> * notify()和notifyAll()方法的區別在於: * <ul> * <li>notify():隨機喚醒一個wait()的線程</li> * <li>notifyAll():喚醒所有wait()的線程</li> * </ul> * </p> * * <pre> * author XueQi * date 16/5/1 * </pre> */ public class SimpleWaitNotify { final static Object OBJECT = new Object(); public static class T1 implements Runnable { @Override public void run() { synchronized (OBJECT) { System.out.println(System.currentTimeMillis() + ":T1 start!"); try { System.out.println(System.currentTimeMillis() + ":T1 wait for object"); OBJECT.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis() + ":T1 end!"); } } } public static class T2 implements Runnable { @Override public void run() { synchronized (OBJECT) { System.out.println(System.currentTimeMillis() + ":T2 start!"); try { System.out.println(System.currentTimeMillis() + ":T2 wait for object"); OBJECT.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis() + ":T2 end!"); } } } public static class T3 implements Runnable { @Override public void run() { Thread.yield(); synchronized (OBJECT) { System.out.println(System.currentTimeMillis() + ":T3 start! notify one thread"); OBJECT.notify(); System.out.println(System.currentTimeMillis() + ":T3 end!"); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static class T4 implements Runnable { @Override public void run() { Thread.yield(); synchronized (OBJECT) { System.out.println(System.currentTimeMillis() + ":T4 start! notify all thread"); OBJECT.notifyAll(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(System.currentTimeMillis() + ":T4 end!"); } } } public static void main(String[] args) { Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); Thread t3 = new Thread(new T3()); Thread t4 = new Thread(new T4()); t1.start(); t2.start(); t3.start(); //t4.start(); } }
當咱們註釋掉t4.start()時,執行main方法.咱們能夠看到控制檯只有一個線程end,另一個wait的線程因爲監視器對象一直沒有順利得到.隊列
當咱們註釋掉t3.start(),執行main方法,能夠看到全部wait的線程都被喚醒,並且是有順序,不是同時被喚醒的.
it