我有两个班级Threads
和ProducerConsumer
。在Thread
中我运行了两个线程:一个用于添加元素,第二个用于删除添加的元素。
问题是在删除第一个元素后consume()
中,notify不会唤醒wait方法。在第二次迭代中,它正在通知。
我的要求是我希望每次迭代都通知生产者。我需要做什么?
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();
}
}
}
答案 0 :(得分:0)
当我运行此代码时,它会产生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();
}
}
}
}
注意循环内的同步是如何发生的,这意味着每次迭代都会释放它。这使产品线程有机会抓住它。生成线程放弃它的原因 - 允许消费线程获取它并保持它,即使它们都声明方法同步 - 是因为wait方法释放了监视器锁。