通知方法不唤醒循环中的等待方法



我有两个类ThreadsProducerConsumerThread我有两个线程正在运行:一个用于添加元素,第二个用于删除添加的任何元素。

问题是,在删除第一个元素后的consume(),通知不会唤醒等待方法。在第二次迭代中,它正在通知。

我的要求是我想在每次迭代时通知生产者。我需要做什么?

public class Threads {
public static void main(String args[]){ 
ProducerConsumer pc = new ProducerConsumer(); 
new Thread(){  
public void run(){pc.produce();}  
}.start();
new Thread(){  
public void run(){pc.consume();}  
}.start();  
}
}


import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class ProducerConsumer {
LinkedList<Integer> list = new LinkedList<>();
public synchronized void produce() {
for(int j = 0; j < 5; j++) {
list.add(j);
System.out.println(list+"producer");
System.out.println("producing and adding values"+j);
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public synchronized void consume() {
for(int j = 0; j < 5; j++) {
System.out.println(list+"list"+"consumer");
list.removeFirst();
System.out.println("consuming values"+j);
notify();
}
}
}

当我运行这段代码时,它会生成一个 NoSuchElementException。问题是,在通知之后,消耗线程不会释放监视器,因此生产将永远不会恢复。对代码的简单修复是以更亲切的方式编写您的消费,如下所示:

public void consume() {
int remaining = 5;
while (remaining > 0) {
synchronized (this) {
if (!list.isEmpty()) {
System.out.println(list + "list" + "consumer");
final int value = list.removeFirst();
System.out.println("consuming value " + value);
remaining--;
notify();
}
}
}
}

请注意同步在循环中的发生方式,这意味着每次迭代都会释放同步。这给了生产线程一个抓住它的机会。生产线程放弃它的原因是 - 允许消费线程获取它并保留它,即使它们都声明方法同步 - 是因为等待方法释放了监视器锁。

最新更新