我有两个类Threads
和ProducerConsumer
。Thread
我有两个线程正在运行:一个用于添加元素,第二个用于删除添加的任何元素。
问题是,在删除第一个元素后的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();
}
}
}
}
请注意同步在循环中的发生方式,这意味着每次迭代都会释放同步。这给了生产线程一个抓住它的机会。生产线程放弃它的原因是 - 允许消费线程获取它并保留它,即使它们都声明方法同步 - 是因为等待方法释放了监视器锁。