java - Java中生产者-消费者代码的多线程没有给出正确的输出?

标签 java multithreading wait notify

我正在使用多线程解决经典的生产者-消费者问题。我正在使用wait()notifyAll()在代码中。我的问题是何时notifyAll通知其他等待线程恢复,但它不会立即恢复。这是为什么?代码如下

public class ConsumerProducer {

 private  int count;

 public synchronized void consume() {
  while (count == 0) {  // keep waiting if nothing is produced to consume
   try {
    wait(); // give up lock and wait
   } catch (InterruptedException e) {
    // keep trying
   }
  }

  count--;              // consume
  System.out.println(Thread.currentThread().getName() + " after consuming " + count);
 }

 public synchronized void produce() {
  count++;             //produce
  System.out.println(Thread.currentThread().getName() + " after producing " + count);
  notifyAll();         // notify waiting threads to resume
 }

}

客户端代码:

public class ConsumerProducerTest implements Runnable {

 boolean isConsumer;
 ConsumerProducer cp;

 public ConsumerProducerTest(boolean isConsumer, ConsumerProducer cp) {
  this.isConsumer = isConsumer;
  this.cp = cp;
 }

 public static void main(String[] args) {
  ConsumerProducer cp = new ConsumerProducer(); //shared by both threads to communicate

  Thread producer = new Thread(new ConsumerProducerTest(false, cp));
  Thread consumer = new Thread(new ConsumerProducerTest(true, cp));

  producer.start();
  consumer.start();
  //producer.start();


 }

 @Override
 public void run() {
  for (int i = 1; i <= 10; i++) {
   if (!isConsumer) {
    cp.produce();
   } else {
    cp.consume();
   }
  }

输出为:

Thread-1 after producing 1
Thread-1 after producing 2
Thread-1 after producing 3
Thread-1 after producing 4
Thread-1 after producing 5
Thread-1 after producing 6
Thread-1 after producing 7
Thread-1 after producing 8
Thread-1 after producing 9
Thread-1 after producing 10
Thread-2 after consuming 9
Thread-2 after consuming 8
Thread-2 after consuming 7
Thread-2 after consuming 6
Thread-2 after consuming 5
Thread-2 after consuming 4
Thread-2 after consuming 3
Thread-2 after consuming 2
Thread-2 after consuming 1
Thread-2 after consuming 0

打印上面的第一行后,调用notifyAll并且等待线程应该恢复,打印Thread-2 after consuming 0 。我看到的问题是在 Thread-1 (Thread-1 after producing) 之后完成后,Thread-2 恢复。但两者应该同时发生吗? 请帮我一下。 谢谢 编辑: 在 main 方法中使用 join() ,不会改变输出:

 producer.start();
  producer.join();
  consumer.start(); 

最佳答案

But both are supposed to happen concurrently?

这里的问题是生产(和消费)只需要很少的时间。你看到的就是所谓的(非关键)race condition生产者甚至可以在消费者开始之前生产所有 10 种商品。通过竞争条件,我的意思是你的两个线程正在相互竞争以生产和消费,在这种情况下不是错误。

如果您将测试增加到(比方说)100000 个项目,您会看到生产和消费消息混合在一起,尽管即使如此,您也可能会看到生产消费 消息 block 长度为 10 或更长。

要尝试的另一件事是首先启动消费者,然后在启动它后放置一个 Thread.sleep(10); ,以便它等待生产者。然后,消费者将有时间调用 wait(),并且一旦第一个 notifyAll 就会从 WAIT 转移到 BLOCKED () 被调用。但即便如此,竞争条件也可能会在消费之前显示所有生产消息。这就是多线程应用程序的异步本质。

附:正确处理 InterruptedException 始终是一个很好的模式。你应该这样做:

try {
    wait(); // give up lock and wait
} catch (InterruptedException e) {
    // reset the thread interrupt flag
    Thread.currentThread().interrupt();
    // probably stopping the thread is best
    return;
}

关于java - Java中生产者-消费者代码的多线程没有给出正确的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18521674/

相关文章:

java - Java 的原语是一等公民吗?

python - 启动 Python 进程后 wait() 返回 -1,errno=10

c++ - 等待函数和 CloseHandle 依赖

java - 如何在只有一个 web 驱动程序实例的 testng 套件中运行多个测试类?

java - 如何从JFrame中选择图像然后上传到imgur?

java - 游戏中的 Random 与 SecureRandom

Java 多线程 - 线程安全计数器

java - ThreadPoolExecutor 挂起

java - 同步函数,还是在线程中锁定对象?

java - 暂停 Swing GUI