1. 使用注意事項
1、永遠在synchronized的函數或對象裏使用wait、notify和notifyAll,不然Java虛擬機會生成IllegalMonitorStateException。
2、永遠在while循環裏而不是if語句下使用wait。這樣,循環會在線程睡眠前後都檢查wait的條件,並在條件實際上並未改變的情況下處理喚醒通知。
3、永遠在多線程間共享的對象上使用wait。
4、notify隨機通知一個阻塞在對象上的線程;notifyAll通知阻塞在對象上所有的線程。
2. 代碼示例
2.1 生產者
public class Producer implements Runnable{
private Queue<Integer> queue;
private int maxSize;
public Producer(Queue<Integer> queue, int maxSize){
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true){
synchronized (queue){
while (queue.size() == maxSize){
try{
System.out.println("Queue is Full");
queue.wait();
}catch (InterruptedException ie){
ie.printStackTrace();
}
}
Random random = new Random();
int i = random.nextInt();
System.out.println("Produce " + i);
queue.add(i);
queue.notifyAll();
}
}
}
}
2.2 消費者
public class Consumer implements Runnable{
private Queue<Integer> queue;
private int maxSize;
public Consumer(Queue<Integer> queue, int maxSize){
this.queue = queue;
this.maxSize = maxSize;
}
@Override
public void run() {
while (true){
synchronized (queue){
while (queue.isEmpty()){
System.out.println("Queue is Empty");
try{
queue.wait();
}catch (InterruptedException ie){
ie.printStackTrace();
}
}
int v = queue.remove();
System.out.println("Consume " + v);
queue.notifyAll();
}
}
}
}
2.3 Main
public class Main {
public static void main(String[] args){
Queue<Integer> queue = new LinkedList<>();
int maxSize = 10;
Producer p = new Producer(queue, maxSize);
Consumer c = new Consumer(queue, maxSize);
Thread pT = new Thread(p);
Thread pC = new Thread(c);
pT.start();
pC.start();
}
}
3. 參考
https://www.cnblogs.com/plmnko/archive/2010/10/15/1851854.html