java中關於執行緒間協作所用關鍵字synchronized,wait,notify的用法

Franson發表於2016-06-30

wait/notify()關鍵字適用於一個執行緒通知另一個執行緒所需的條件狀態已就緒,最常用於執行緒在迴圈中休眠直到獲取特定條件的場景. 例如,一個執行緒一直等待直到佇列中有一個元件能夠處理;當元件新增到佇列時,另一個執行緒能夠喚醒這個等待的執行緒。

如下程式碼演示執行緒間的協作:

package thread_waitnotify;

public class ProductFactory {
    class Worker implements Runnable {
        private final Object lockObject = new Object();
        private volatile boolean hasWork = false;

        private void waitTakeTask() {
            synchronized (lockObject) {
                while (!hasWork) {
                    try {
                        System.out.println("等待中...");
                        lockObject.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                takeTask();
            }
        }

        private void takeTask() {
            boolean tmpHasWork = false;
            synchronized (lockObject) {
                if (hasWork)
                    tmpHasWork = true;
            }
            if (tmpHasWork) {
                System.out.println("開始做任務...");
                try {
                    Thread.sleep(3000);
                    synchronized (lockObject) {
                        hasWork = false;
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println("任務完成,休息3s後退出...");
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // System.out.println("任務完成,繼續尋找下一項任務...");
                // takeTask();
            } else {
                System.out.println("暫時沒有任務,進入等待狀態...");
                waitTakeTask();
            }
        }

        public void notifyChange() {
            synchronized (lockObject) {
                hasWork = true;
                System.out.println("起床開工了...");
                lockObject.notifyAll();// 喚醒所有等待獲取lockObject鎖的執行緒
            }
        }

        @Override
        public void run() {
            takeTask();
        }
    }

    public static void main(String[] args) throws InterruptedException {

        Worker worker = new ProductFactory().new Worker();
        Thread thread = new Thread(worker);
        thread.start();
        Thread.sleep(3000);// 主執行緒休眠3s後喚醒子執行緒
        worker.notifyChange();// 主執行緒設定子執行緒中的訊號量並喚醒阻塞的執行緒

        thread.join();// 主執行緒阻塞,等待子執行緒執行完成後繼續主執行緒的執行
        System.out.println("子執行緒執行完成,主執行緒退出。");
        System.exit(0);
    }

}

執行結果如下所示:

說一下synchronized和wait()、notify()的關係:

1.有synchronized的地方不一定有wait,notify

2.有wait,notify的地方必有synchronized.這是因為wait和notify不是屬於執行緒類,而是每一個物件都具有的方法,而且,這兩個方法都和物件鎖有關,有鎖的地方,必有synchronized。

相關文章