我的农产品消费者挂起
Posted
技术标签:
【中文标题】我的农产品消费者挂起【英文标题】:My Produce Consumer Hangs 【发布时间】:2011-03-05 07:36:21 【问题描述】:请复制下面的程序并尝试在您的 IDE 中运行。这是一个简单的 Producer 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;
【问题讨论】:
【参考方案1】:问题是您使用 queue.notify() 只会唤醒等待队列的单个线程。想象一下 Producer 1 调用 notify() 并唤醒 Producer 2。Producer 2 看到队列中有东西,所以他没有生产任何东西,只是回到 wait() 调用。现在你的生产者和消费者都在等待通知,没有人在工作来通知任何人。
要解决代码中的问题,请使用 queue.notifyAll() 唤醒在 wait() 中阻塞的每个线程。这将允许您的消费者运行。
请注意,您的实现将队列限制为最多包含一个项目。所以你不会从第二组生产者和消费者中看到任何好处。为了更好的实现,我建议您查看BlockingQueue 并使用可以有界的实现,例如ArrayBlockingQueue。无需同步和使用等待/通知,只需使用BlockingQueue.offer() 和BlockingQueue.take()。
【讨论】:
哎呀.. 傻我.. 终于我可以使用 notifyAll().. 非常感谢!!【参考方案2】:使用 queue.notifyAll() 代替 queue.notify()
【讨论】:
以上是关于我的农产品消费者挂起的主要内容,如果未能解决你的问题,请参考以下文章