1 回答
TA贡献1829条经验 获得超7个赞
更改代码中出现的iftowhile可以解决问题。
Oracle 网站上的Guarded Blocks 教程中有相关建议,其中说:
注意:始终在测试等待条件的循环内调用 wait。不要假设中断是针对您正在等待的特定条件,或者条件仍然为真。
(中断是指从等待中返回,不一定是来自调用 Thread.interrupt 的人的实际中断。)
关键点:
只有当线程在检查时持有锁时,它才知道货物列表的内容。
调用 wait 会放弃锁,允许其他线程在这个线程处于休眠状态时取得进展。
一旦线程放弃锁,它之前对货物列表状态所做的任何检查都不再有效。
一旦线程从等待中返回,它就重新获得了锁,但该线程需要重新评估条件检查,否则它正在处理陈旧的信息。在线程上次检查条件的时间和当前时间之间可能发生了很多事情。您得到 IllegalArgumentException 是因为当前线程假设在当前线程等待时另一个线程删除了某些东西。
package com.threading;
import java.util.ArrayList;
import java.util.List;
public class TestConsumerProducer2 {
protected static int maxSize = 2;
static class Consumer implements Runnable {
List<Integer> goods;
public Consumer(List<Integer> goods) {
this.goods = goods;
}
public void consume() {
synchronized (goods) {
while (goods.size() <= 0) {
try {
goods.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " >>>> consuming >>>" + goods.remove(0));
goods.notifyAll();
}
}
@Override
public void run() {
for (int i = 0; i < 10; i++) {
consume();
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
static class Producer implements Runnable {
List<Integer> goods;
public Producer(List<Integer> goods) {
this.goods = goods;
}
public void produce(int i) {
synchronized (goods) {
while (goods.size() >= maxSize) {
try {
goods.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + ">>> producing >> " + i);
goods.add(i);
goods.notifyAll();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < 10; i++) {
produce(i);
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
List<Integer> goods = new ArrayList<>();
Consumer consumer = new Consumer(goods);
Producer producer = new Producer(goods);
Thread consumerWorker1 = new Thread(consumer);
Thread consumerWorker2 = new Thread(consumer);
Thread prroducerWorker1 = new Thread(producer);
Thread prroducerWorker2 = new Thread(producer);
consumerWorker1.start();
consumerWorker2.start();
prroducerWorker1.start();
prroducerWorker2.start();
try {
consumerWorker1.join();
consumerWorker2.join();
prroducerWorker1.join();
prroducerWorker2.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Job completed >>>>");
}
}
代码现在成功完成,输出如下:
C:\>java com.threading.TestConsumerProducer2
Thread-2>>> producing >> 0
Thread-1 >>>> consuming >>>0
Thread-3>>> producing >> 0
Thread-0 >>>> consuming >>>0
Thread-2>>> producing >> 1
Thread-3>>> producing >> 1
Thread-0 >>>> consuming >>>1
Thread-1 >>>> consuming >>>1
Thread-2>>> producing >> 2
Thread-3>>> producing >> 2
Thread-0 >>>> consuming >>>2
Thread-1 >>>> consuming >>>2
Thread-2>>> producing >> 3
Thread-0 >>>> consuming >>>3
Thread-3>>> producing >> 3
Thread-1 >>>> consuming >>>3
Thread-2>>> producing >> 4
Thread-0 >>>> consuming >>>4
Thread-3>>> producing >> 4
Thread-1 >>>> consuming >>>4
Thread-2>>> producing >> 5
Thread-0 >>>> consuming >>>5
Thread-3>>> producing >> 5
Thread-1 >>>> consuming >>>5
Thread-2>>> producing >> 6
Thread-0 >>>> consuming >>>6
Thread-3>>> producing >> 6
Thread-1 >>>> consuming >>>6
Thread-2>>> producing >> 7
Thread-0 >>>> consuming >>>7
Thread-3>>> producing >> 7
Thread-1 >>>> consuming >>>7
Thread-2>>> producing >> 8
Thread-0 >>>> consuming >>>8
Thread-3>>> producing >> 8
Thread-1 >>>> consuming >>>8
Thread-2>>> producing >> 9
Thread-0 >>>> consuming >>>9
Thread-3>>> producing >> 9
Thread-1 >>>> consuming >>>9
Job completed >>>>
添加回答
举报