我的产品消费者挂起 [英] My Produce Consumer Hangs

查看:113
本文介绍了我的产品消费者挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请复制下面的程序,然后尝试在您的IDE中运行.这是一个简单的Producer消费者实现-当我使用一个Producer和一个Consumer线程时,它运行良好,但当每个使用2个消费者线程时却失败.请让我知道该程序挂起的原因或其他问题.

Please copy the program below and try running in your IDE. It's a simple Produce Consumer implementation - it runs fine when I use one Producer and one Consumer thread but fails when using 2 each. Please let me know the reason why this program hangs or is there anything else wrong with it.

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(),它只会唤醒等待队列的单个线程.想象一下,生产者1调用notify()并唤醒生产者2.生产者2看到队列中有东西,因此他不产生任何东西,只是返回到wait()调用.现在,您的生产者和消费者都在等待通知,没有人可以通知任何人.

The problem is that you are using queue.notify() which will only wake up a single Thread waiting on the Queue. Imagine Producer 1 calls notify() and wakes up Producer 2. Producer 2 sees that there is something in the queue so he doesn't produce anything and simply goes back to the wait() call. Now both your Producers and Consumers are all waiting to be notified and nobody is left working to notify anyone.

要解决代码中的问题,请使用queue.notifyAll()唤醒在wait()处阻塞的每个线程.这将使您的消费者能够运行.

To solve the problem in your code, use queue.notifyAll() to wake up every Thread blocked at a wait(). This will allow your consumers to run.

请注意,您的实现将队列限制为其中最多包含一个项目.因此,您将看不到第二组生产者和消费者的任何好处.为了更好地实施,我建议您查看 BlockingQueue.offer()

As a note, your implementation limits the queue to having at most one item in it. So you won't see any benefit from the second set of producers and consumers. For a better all around implementation, I suggest you look at BlockingQueue and use an implementation which can be bounded, for instance, the ArrayBlockingQueue. Instead of synchronizing and using wait/notify, simply use BlockingQueue.offer() and BlockingQueue.take().

这篇关于我的产品消费者挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆