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。