我一直在努力解决这个简单的并发Oracle问题,它为生产者/消费者建模。这是我第一次使用防护块,等待和notifyAll。但是,我知道这些方法的用途;我不先发生什么步骤。我将在下面尽可能地追踪问题,你们可以告诉我,如果我是对的。
drop.take()
的消息。但是,生产者没有向消费者提供消息,因为empty
是真的。这导致线程被挂起并且锁被释放。现在正在等待。 drop.put()
。它获取drop上的内在锁定并继续该方法,因为empty
为真,它需要为Consumer准备消息。它将empty
设置为false并存储消息。调用notifyAll()
来唤醒消费者线程。生产者也在等待,因为empty
现在为假并且锁被释放。 drop.take()
已被通知且生产者具有内在锁定,因此它会唤醒该方法。 Empty
设置为true,并在循环中返回并打印消息。它现在通知生产者线程唤醒,因为它需要一条新消息。empty
为真并且已通知线程(并且已访问锁),因此它现在可以唤醒并生成另一条消息。 Drop Class
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();
}
}
答案 0 :(得分:0)
我没有完整的答案,但我确实有一些观察。
while while包含等待将导致异常,如果它们循环。等待需要锁定,但等待释放锁定。幸运的是,你不应该经历这种行为。
您可能会遇到不跨线程更新实例变量的问题。你同步,然后等待。这为这些变量提供了不同价值的机会。将它们标记为不稳定将有助于此。
你没有说出你的代码实际上做了什么......