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