【发布时间】:2017-12-10 18:25:54
【问题描述】:
我已经为这个简单的并发 Oracle 问题苦苦挣扎了几天,它模拟了生产者/消费者。这是我第一次使用受保护的块、等待和 notifyAll。但是,我知道这些方法的作用;我不知道先发生什么步骤。我将尽我所能在下面追踪问题,你们可以告诉我我是否正确。
- 生产者/消费者线程从主线程启动。每个都被赋予相同的 Drop 实例。
- 如果消费者线程比生产者线程快,它会在 drop 上获取内在锁定并尝试在循环中打印来自
drop.take()的消息。但是,生产者没有给消费者消息,因为empty是真的。这导致线程被挂起并释放锁。它现在正在等待。 - 生产者线程循环调用
drop.put()。它在删除时获取内在锁定并继续该方法,因为empty为真,它需要为消费者准备消息。它将empty设置为false 并存储消息。调用notifyAll()唤醒消费者线程。 Producer 也在等待,因为empty现在为 false 并且锁被释放。 - 由于
drop.take()被通知并且Producer 具有对drop 的内在锁定,它唤醒了该方法。Empty设置为 true 并在循环中返回并打印消息。它现在通知生产者线程唤醒,因为它需要一条新消息。 - 生产者一直在等待。由于
empty为真并且线程已被通知(并且锁已被访问),它现在可以唤醒并产生另一条消息。
删除类
package Store;
public class Drop {
// Message sent from producer
// to consumer.
private String message;
// True if consumer should wait
// for producer to send message,
// false if producer should wait for
// consumer to retrieve message.
private boolean empty = true;
public synchronized String take() {
// Wait until message is
// available.
while (empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = true;
// Notify producer that
// status has changed.
notifyAll();
return message;
}
public synchronized void put(String message) {
// Wait until message has
// been retrieved.
while (!empty) {
try {
wait();
} catch (InterruptedException e) {}
}
// Toggle status.
empty = false;
// Store message.
this.message = message;
// Notify consumer that status
// has changed.
notifyAll();
}
}
消费类:
package Store;
import java.util.Random;
public class Consumer implements Runnable {
private Drop drop;
public Consumer(Drop drop) {
this.drop = drop;
}
public void run() {
Random random = new Random();
for (String message = drop.take();
! message.equals("DONE");
message = drop.take()) {
System.out.format("MESSAGE RECEIVED: %s%n", message);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
}
}
生产者类:
package Store;
import java.util.Random;
public class Producer implements Runnable {
private Drop drop;
public Producer(Drop drop) {
this.drop = drop;
}
public void run() {
String importantInfo[] = {
"Mares eat oats",
"Does eat oats",
"Little lambs eat ivy",
"A kid will eat ivy too"
};
Random random = new Random();
for (int i = 0;
i < importantInfo.length;
i++) {
drop.put(importantInfo[i]);
try {
Thread.sleep(random.nextInt(5000));
} catch (InterruptedException e) {}
}
drop.put("DONE");
}
}
主线程:
public class ProducerConsumerExample {
public static void main(String[] args) {
Drop drop = new Drop();
(new Thread(new Producer(drop))).start();
(new Thread(new Consumer(drop))).start();
}
}
【问题讨论】:
标签: java concurrency