这个例子有点局限,消费者每次只能等生产者生产了n个Q后消费完这n个。
package com.test;
class Q {
int n;
boolean valueSet = false; //Q的value是不是已经设置过了
synchronized int get() {
if(!valueSet)
try {
wait(); //wait until Producer produce a product and notify ,释放锁
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Got: " + n);
valueSet = false;
notify();
return n;
}
synchronized void put(int n) {
if(valueSet)
try {
wait();
} catch(InterruptedException e) {
System.out.println("InterruptedException caught");
}
this.n = n;
valueSet = true;
System.out.println("Put: " + n);
notify();
}
}
class Producer implements Runnable {
Q q;
Producer(Q q) {
this.q = q;
new Thread(this, "Producer").start();
}
public void run() {
int i = 0;
while(true) {
q.put(i++);
}
}
}
class Consumer implements Runnable {
Q q;
Consumer(Q q) {
this.q = q;
new Thread(this, "Consumer").start();
}
public void run() {
while(true) {
q.get();
}
}
}
class PCFixed {
public static void main(String args[]) {
Q q = new Q();
new Consumer(q);
new Producer(q);
System.out.println("Press Control-C to stop.");
}
}
下面的方法转自《程序员面试攻略》第二版,机械工业出版社,P118-P119,应该是正确的解答:
生产者:
public class Producer extends Thread {
private IntBuffer buffer;
public Producer(IntBuffer buffer) {
this.buffer = buffer;
}
public void run() {
Random r = new Random();
while(true) {
int num = r.nextInt();
buffer.add(num);
System.out.println("Produced " + num);
}
}
}
消费者:
public class Consumer extends Thread {
private IntBuffer buffer;
public Consumer(IntBuffer buffer) {
this.buffer = buffer;
}
public void run() {
while(true) {
int num = buffer.remove();
System.out.println("Consumed " + num);
}
}
}
缓冲区:
public class IntBuffer {
private int index;
private int[] buffer = new int[8];
public synchronized void add( int num ) {
while(index == buffer.length-1) {
try {
wait();
}catch(InterruptedException e) {
}
}
buffer[index++] = num;
notifyAll();
}
public synchronized int remove() {
while(index == 0) {
try {
wait();
}catch(InterruptedException e) {
}
}
int ret = buffer[--index];
notifyAll();
return ret;
}
}
这段代码允许多个生产者和多个消费者使用同一个缓冲区,解决了第一个方法的缺陷。