wait() notify() notifyAll()小結

1.wait()和notify()是如何工做的?

    這兩個方法不併在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

    要注意:上面的過程並非公平的,不會由於你的線程優先級高,或者先進入等待隊列而被優先選擇,是徹底隨機的.線程


2.notify()和notifyAll()的區別

    除了notify()方法外,Object類還有一個方法是:notifyAll()方法.它和notify()的用法基本一致,但不一樣的是,它會喚醒線程等待隊列中全部等待的線程,而不是隨機選擇一個.code


3.wait() notify() notifyAll()的使用方法

    首先須要強調的是:這三個方法不是隨便就能夠調用的.它們必須包含在對應的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

相關文章
相關標籤/搜索