Java中用于生产者 - 消费者代码的mutithreading没有提供正确的输出?

bra*_*orm 0 java multithreading notify wait

我正在使用多线程来解决经典的生产者 - 消费者问题.我正在使用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
 }

}
Run Code Online (Sandbox Code Playgroud)

客户代码:

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();
   }
  }
Run Code Online (Sandbox Code Playgroud)

输出是:

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
Run Code Online (Sandbox Code Playgroud)

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

 producer.start();
  producer.join();
  consumer.start(); 
Run Code Online (Sandbox Code Playgroud)

Gra*_*ray 8

但两者都应该同时发生?

这里的问题是生产(和消费)只需要很少的时间.您正在看到所谓的(非关键)竞争条件,并且生产者能够在消费者开始之前生成所有10个项目.根据竞争条件,我的意思是你的两个线程相互竞争生产和消费,而不是在这种情况下的错误.

如果您将测试增加到(假设)100000个项目,您会看到混合生成和消费消息,尽管如此,您可能会看到长度为10或更多的块producingconsuming消息.

要尝试的另一件事是首先启动消费者并Thread.sleep(10);在启动它之后放置它以便它等待生产者.然后,消费者将有时间打电话,wait()并在第一次被呼叫时立即转移WAIT到.但即便如此,竞争条件可能会在之前显示所有消息.这是多线程应用程序的异步特性.BLOCKEDnotifyAll()producingconsuming

ps正确处理它总是一个好的模式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;
}
Run Code Online (Sandbox Code Playgroud)

  • 维基百科区分"非关键竞争条件"(不能导致错误的竞赛)和"关键竞争条件"(可能导致错误的竞赛).我认为,OP的例子将是一种"非关键竞争条件",因为所有预期值最终都会产生,所有预期值最终都会被消耗,这通常是基本生产者/消费者模式的唯一要求.此外,没有死锁或活锁的风险,并且给定合理的CPU时间,所有线程都将运行完成. (2认同)