我的农产品消费者悬挂
-
28-09-2019 - |
题
请复制下面的程序,然后尝试在您的IDE中运行。这是一个简单的农产品消费者实现 - 当我使用一个生产者和一个消费者线程时,它运行良好,但使用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;
}
}
解决方案
问题在于您正在使用queue.notify(),该notify()只会唤醒一个在队列上等待的单个线程。想象一下生产者1呼叫通知()并唤醒生产者2。生产者2看到队列中有东西,因此他没有生产任何东西,然后简单地回到wait()呼叫。现在,您的生产者和消费者都在等待通知,没有人努力通知任何人。
要解决代码中的问题,请使用queue.notifyall()唤醒在wait()中阻止的每个线程。这将使您的消费者能够运行。
注意,您的实施将队列限制在其中最多有一项。因此,您将不会从第二组生产商和消费者那里看到任何好处。为了在实施方面做得更好,我建议您看看 阻塞 并使用实现,例如 Arrayblockingqueue. 。而不是同步和使用等待/通知,只需使用 blockingqueue.offer() 和 blockingqueue.take().
其他提示
而不是queue.notify()使用queue.notifyall()
不隶属于 StackOverflow