我正在刷新我对Java并发的记忆,我正在玩流行的生产者消费者问题。我已经实现了以下代码,如果有一个生产者和一个消费者,它可以正常工作。但是,如果有多个生产者/消费者,它将无法正常运行。我不明白为什么
public class ProducerConsumer {
static Monitor monitor;
public ProducerConsumer(int maxSize)
{
monitor = new Monitor(maxSize);
new Producer().start();
new Producer().start();
new Consumer().start();
new Consumer().start();
}
class Producer extends Thread{
@Override
public void run() {
while(true)
{
try {
monitor.insert();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Consumer extends Thread{
@Override
public void run() {
while(true)
{
try {
monitor.remove();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Monitor {
int n;
int maxSize;
public Monitor(int maxSize)
{
n=0;
this.maxSize = maxSize;
}
synchronized void insert() throws InterruptedException
{
if(n==maxSize)
wait();
System.out.println("Producer: "+n++);
if(n==1)
notifyAll();
}
synchronized void remove() throws InterruptedException
{
if(n==0)
wait();
System.out.println("Consumer: "+n--);
if(n==maxSize-1)
notifyAll();
}
}
public static void main(String[] args) {
ProducerConsumer pc = new ProducerConsumer(100);
}
}
答案 0 :(得分:8)
wait()
应始终按以下方式使用:
while(condition not met)
wait();
否则某些线程可以唤醒并在条件仍未满足时继续。这种情况有两种可能的原因:
notifyAll()
时,你唤醒所有等待的线程,因此当条件再次为假时(即当有限的资源已经被其他线程耗尽时),其中一些可能为时已太晚。notify
的情况下醒来。)如果您实际上只需唤醒一个主题,则可以使用notify()
代替notifyAll()
。它消除了第一个问题,但仍无法保护您免受虚假唤醒,因此仍然需要while
。