线程中生产者消费者的误区
Producer Consumer Misunderstanding in Threading
我希望 ProducerThread 生成最多 10 的随机值,然后期望 ConsumerThread 消费 Queue 的这些值。 Producer 在某处生成多次添加值。我有一个概念,当我们在一个对象上调用 notify 时,Thread 会释放锁并给等待更新的 Thread 机会。
这是代码,请指正我的理解。
public class ProducerThread extends Thread {
Queue<Integer> values;
ProducerThread(Queue<Integer> values) {
this.values = values;
}
public void run() {
while(true) {
synchronized(values) {
double totalValues = Math.random()*10;
System.out.println("Going to populate total values:" + totalValues);
for (int i = 1; i <= totalValues; i++) {
values.add(i);
System.out.println("Value updated: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
values.notify();
}
}
}
}
public class ConsumerThread extends Thread {
Queue<Integer> values;
ConsumerThread(Queue<Integer> values) {
this.values = values;
}
@Override
public void run() {
while(true) {
synchronized (values) {
try {
// Consumer Thread waits until values are populated by Producer Thread
if(values.isEmpty()) {
values.wait();
}
Iterator<Integer> iterateValues = values.iterator();
System.out.println("Going to consume values: " + values.size());
while (iterateValues.hasNext()) {
Integer removedValue = iterateValues.next();
System.out.println("Value deleted: " + removedValue);
}
values.clear();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String[] args) {
Queue<Integer> values = new LinkedList<Integer>();
ProducerThread producer = new ProducerThread(values);
ConsumerThread consumer = new ConsumerThread(values);
consumer.start();
producer.start();
}
}
啊哈!您遇到了可怕的竞争条件!
在您的 ProducerThread
notify
return 秒之后,所述线程仍具有锁。被 notify
唤醒的 ConsumerThread
会发现锁不可用,并会等到它可用。
然后 ProducerThread
放弃锁,然后它将与 ConsumerThread
进行竞争以取回该锁(ProducerThread
通过重新进入 synchronized
块,并且 ConsumerThread
必须从 wait
到 return)。无法保证其中哪一个会获胜。
如果您希望 ProducerThread
等待物品被消耗后再生产更多,您应该考虑另一个 wait/notify 用于该场景。
编辑:这张图片可能有助于更清楚地解释事情。
我希望 ProducerThread 生成最多 10 的随机值,然后期望 ConsumerThread 消费 Queue 的这些值。 Producer 在某处生成多次添加值。我有一个概念,当我们在一个对象上调用 notify 时,Thread 会释放锁并给等待更新的 Thread 机会。
这是代码,请指正我的理解。
public class ProducerThread extends Thread {
Queue<Integer> values;
ProducerThread(Queue<Integer> values) {
this.values = values;
}
public void run() {
while(true) {
synchronized(values) {
double totalValues = Math.random()*10;
System.out.println("Going to populate total values:" + totalValues);
for (int i = 1; i <= totalValues; i++) {
values.add(i);
System.out.println("Value updated: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
values.notify();
}
}
}
}
public class ConsumerThread extends Thread {
Queue<Integer> values;
ConsumerThread(Queue<Integer> values) {
this.values = values;
}
@Override
public void run() {
while(true) {
synchronized (values) {
try {
// Consumer Thread waits until values are populated by Producer Thread
if(values.isEmpty()) {
values.wait();
}
Iterator<Integer> iterateValues = values.iterator();
System.out.println("Going to consume values: " + values.size());
while (iterateValues.hasNext()) {
Integer removedValue = iterateValues.next();
System.out.println("Value deleted: " + removedValue);
}
values.clear();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
public class Test {
public static void main(String[] args) {
Queue<Integer> values = new LinkedList<Integer>();
ProducerThread producer = new ProducerThread(values);
ConsumerThread consumer = new ConsumerThread(values);
consumer.start();
producer.start();
}
}
啊哈!您遇到了可怕的竞争条件!
在您的 ProducerThread
notify
return 秒之后,所述线程仍具有锁。被 notify
唤醒的 ConsumerThread
会发现锁不可用,并会等到它可用。
然后 ProducerThread
放弃锁,然后它将与 ConsumerThread
进行竞争以取回该锁(ProducerThread
通过重新进入 synchronized
块,并且 ConsumerThread
必须从 wait
到 return)。无法保证其中哪一个会获胜。
如果您希望 ProducerThread
等待物品被消耗后再生产更多,您应该考虑另一个 wait/notify 用于该场景。
编辑:这张图片可能有助于更清楚地解释事情。