请复制以下程序并尝试在IDE中运行。这是一个简单的Produce Consumer实现 - 当我使用一个Producer和一个Consumer线程时它运行正常但在使用2时每个都运行失败。请告诉我这个程序挂起的原因或是否还有其他问题。
import java.util.LinkedList;
import java.util.Queue;
public class PCQueue {
private volatile Queue<Product> productQueue = new LinkedList<Product>();
public static void main(String[] args) {
PCQueue pc = new PCQueue();
Producer producer = new Producer(pc.productQueue);
Consumer consumer = new Consumer(pc.productQueue);
new Thread(producer, "Producer Thread 1").start();
new Thread(consumer, "Consumer Thread 1").start();
new Thread(producer, "Producer Thread 2").start();
new Thread(consumer, "Consumer Thread 2").start();
}
}
class Producer implements Runnable {
private Queue<Product> queue = null;
private static volatile int refSerialNumber = 0;
public Producer(Queue<Product> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.peek() != null) {
try {
queue.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
queue.add(new Product(++refSerialNumber));
System.out.println("Produced by: "
+ Thread.currentThread().getName() + " Serial Number: "
+ refSerialNumber);
queue.notify();
}
}
}
}
class Consumer implements Runnable {
private Queue<Product> queue = null;
public Consumer(Queue<Product> queue) {
this.queue = queue;
}
@Override
public void run() {
while (true) {
synchronized (queue) {
while (queue.peek() == null) {
try {
queue.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Product product = queue.remove();
System.out.println("Consumed by: "
+ Thread.currentThread().getName() + " Serial Number: "
+ product.getSerialNumber());
queue.notify();
}
}
}
}
class Product {
private int serialNumber;
public Product(int serialNumber) {
this.serialNumber = serialNumber;
}
public int getSerialNumber() {
return serialNumber;
}
}
答案 0 :(得分:4)
问题是你正在使用queue.notify(),它只会唤醒一个等待队列的线程。想象一下,生产者1调用notify()并唤醒生产者2.生产者2看到队列中有东西,所以他不会产生任何东西,只是回到wait()调用。现在你的制作人和消费者都在等待通知,没有人留下来通知任何人。
要解决代码中的问题,请使用queue.notifyAll()来唤醒在wait()时阻塞的每个线程。这将允许您的消费者运行。
作为注释,您的实现将队列限制为最多包含一个项目。因此,您不会看到第二组生产者和消费者的任何好处。为了更好地实现所有实现,我建议您查看BlockingQueue并使用可以限制的实现,例如ArrayBlockingQueue。不要同步和使用wait / notify,只需使用BlockingQueue.offer()和BlockingQueue.take()。
答案 1 :(得分:1)
而不是queue.notify()使用queue.notifyAll()