java線程的等待、通知機制【讀書筆記】


代碼示例:

package com.baidu.nuomi.concurrent;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * Created by sonofelice on 16/6/18.
 */
public class WaitNotify {
    static boolean flag = true;
    static Object lock = new Object();

    public static void main(String[] args) throws Exception{
        Thread waitThread = new Thread(new Wait(),"WaitThread");
        waitThread.start();
        TimeUnit.SECONDS.sleep(1);
        Thread notifyThread = new Thread(new Notify(),"NotifyThread");
        notifyThread.start();
        
    }
    static class Wait implements Runnable{
        @Override
        public void run() {
            synchronized (lock){
                while (flag){
                    try {
                        System.out.println(Thread.currentThread() + " flag is true. wait @ "
                                + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                        lock.wait();
                    }catch (InterruptedException e){
                    }
                }
                System.out.println(Thread.currentThread() + "flag is false. running @ "
                        + new SimpleDateFormat("HH:mm:ss").format(new Date()));
            }
        }
    }
    static class Notify implements Runnable{
        @Override
        public void run() {
            synchronized (lock){
                System.out.println(Thread.currentThread() + "hold lock. notify @ "
                        + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                lock.notifyAll();
                flag = false;
                SleepUtils.second(5);
            }
            synchronized (lock){
                System.out.println(Thread.currentThread() + "hold lock again. sleep @ "
                        + new SimpleDateFormat("HH:mm:ss").format(new Date()));
                SleepUtils.second(5);
            }
        }
    }
}

輸出如下:

Thread[WaitThread,5,main] flag is true. wait @ 12:21:04
Thread[NotifyThread,5,main]hold lock. notify @ 12:21:05
Thread[NotifyThread,5,main]hold lock again. sleep @ 12:21:10
Thread[WaitThread,5,main]flag is false. running @ 12:21:15

Process finished with exit code 0

調用wait() notify()  notifyAll()方法時需要注意的細節:

1)使用wait() notify()  notifyAll() 時需要先對調用對象加鎖;

2)調用wait()方法后,線程狀態由RUNNING 變為WAITING,並將當前線程放置到對象的等待隊列。

3)notify()或notifyAll() 方法調用后,等待線程依舊不會從wait返回,需要調用notify()或notifyAll()的線程釋放鎖之后,等待線程才有機會從wait()返回。

4)notify()方法將等待隊列中的一個等待線程從等待隊列中移到同步隊列中,而notifyAll()方法則是將等待隊列中的所有的線程全部移到同步隊列,被移動的線程狀態由WAITING變為BLOCKED。

5)從wait()方法返回的前提是獲得了調用對象的鎖。

從上面的細節可以看出,等待/通知機制依托於同步機制,其目的就是確保等待線程從wait()方法返回時能夠感知到通知線程對變量做出的修改。

 

從而抽象出等待/通知的經典范式:

等待方:

1)獲取對象鎖;

2)如果條件不滿足,那么調用對象的wait()方法,被通知后仍要檢查條件。

3)條件滿足則執行對應的邏輯。

對應的偽代碼如下:

synchronized(對象){

while(條件不滿足){

 Object.wait();

}

邏輯處理

}

 

通知方:

1)獲得對象的鎖;

2)改變條件;

3)通知所有等待在對象上的線程。

對應的偽代碼如下:

synchronized(對象){

  改變條件

  對象.notifyAll();

}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM