這三個方法由於需要控制對對象的控制權(monitor),所以屬於Object而不是屬於線程。
wait(),會把持有該對象線程的對象控制權交出去,然后處於等待狀態。
notify(),會通知某個正在等待這個對象的控制權的線程可以繼續運行。
nofifyAll(),會通知所有等待這個對象控制權的線程繼續運行,如果有多個正在等待該對象控制權時,具體喚醒哪個線程,就由操作系統進行調度。
注意:
1.生產者,消費者必須要對同一份資源進行操作。
2.無論是執行對象的wait、notify還是notifyAll方法,必須保證當前運行的線程取得了該對象的控制權(monitor)
生產者:
package com.currentPro.waitAndnotify; import java.util.ArrayList; import java.util.List; public class Producer implements Runnable{ private List<Integer> taskQueue = new ArrayList<Integer>(); //生產的量 private final int MAX_CAPACITY; public Producer(List<Integer> sharedQueue,int size){ this.taskQueue = sharedQueue; this.MAX_CAPACITY = size; } @Override public void run() { int counter = 1; while (true) { try { synchronized (taskQueue) { while (taskQueue.size() == MAX_CAPACITY) { System.out.println("Queue is full " + Thread.currentThread().getName() + " is waiting , size: " + taskQueue.size()); taskQueue.wait(); } Thread.sleep(1000); taskQueue.add(counter); System.out.println("Produced: " + counter); counter++; //喚醒正在等待的消費者,但是消費者是不是能獲取到資源,由系統調度。 taskQueue.notifyAll(); } } catch (InterruptedException ex) { ex.printStackTrace(); } } } }
消費者:
package com.currentPro.waitAndnotify; import java.util.List; public class Consumer implements Runnable{ private final List<Integer> taskQueue ; public Consumer(List<Integer> sharedQueue){ this.taskQueue = sharedQueue; } @Override public void run() { while (true) { try { synchronized (taskQueue) { while (taskQueue.isEmpty()) { System.out.println("Queue is empty " + Thread.currentThread().getName() + " is waiting , size: " + taskQueue.size()); taskQueue.wait(); } Thread.sleep(1000); int i = (Integer) taskQueue.remove(0); System.out.println("Consumed: " + i); taskQueue.notifyAll(); } } catch (InterruptedException ex) { ex.printStackTrace(); } } } }
測試代碼:
package com.currentPro.waitAndnotify; import java.util.ArrayList; import java.util.List; public class Test { public static void main(String[] args) throws InterruptedException { //共享資源 List<Integer> taskQueue = new ArrayList<Integer>(); int MAX_CAPACITY = 5; //創建生產者線程 Thread producer = new Thread(new Producer(taskQueue,MAX_CAPACITY),"producer"); //創建消費者線程 Thread consumer = new Thread(new Consumer(taskQueue),"consumer"); consumer.start(); Thread.sleep(2000); producer.start(); } }
參考資料
http://longdick.iteye.com/blog/453615
http://howtodoinjava.com/core-java/multi-threading/how-to-work-with-wait-notify-and-notifyall-in-java/
http://www.cnblogs.com/dolphin0520/p/3920385.html