0
我一直在爲這幾個模型生產者/消費者的簡單併發Oracle問題掙扎了幾天。這是我第一次使用防護塊,等待和notifyAll。不過,我知道這些方法的作用。我不會先發生什麼步驟。我會盡力追蹤問題,因爲我可以告訴我,如果我是對的,你可以告訴我。在Java中跟蹤保護塊
- 生產者/消費者線程從主線程啓動。每個都被賦予相同的Drop實例。
- 如果客戶線程速度比生產者速度快,則它獲取內在鎖定丟棄並嘗試在一個循環中打印來自
drop.take()
的消息。然而,由於empty
屬實,製片人沒有給消費者留言。這導致線程被掛起並且鎖定被釋放。它現在正在等待。 - 生產者線程在循環中調用
drop.put()
。它獲取內在鎖的下降並繼續該方法,因爲empty
爲真,它需要爲消費者準備消息。它將empty
設置爲false並存儲消息。notifyAll()
被稱爲喚醒消費者線程。生產者也在等待,因爲empty
現在是錯誤的,鎖定被釋放。 - 由於
drop.take()
已收到通知,生產者對內存有固有的鎖定,因此它喚醒了方法。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();
}
}
我只是追蹤第一條消息的步驟,這將重複其他消息。我喜歡你所說的關於如何等待並釋放鎖定的內容。 – retchers