3as*_*awy 2 java concurrency pthreads
我正在刷新我对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);
}
}
Run Code Online (Sandbox Code Playgroud)
wait() 应始终以下列方式使用:
while(condition not met)
wait();
Run Code Online (Sandbox Code Playgroud)
否则一些线程可以唤醒并在条件仍未满足时继续.这种情况有两种可能的原因:
notifyAll(),你唤醒所有等待的线程,因此当条件再次为假时(即当有限的资源已被其他线程耗尽时),其中一些可能为时已晚.notify).如果你实际上只需要唤醒一个线程,你可以使用notify()而不是notifyAll().它消除了第一个问题,但仍然无法保护您免受虚假唤醒,因此while仍然需要.