在java中,我試圖使用下面的代碼使用簡單的wait和notifyAll()方法編寫生產者和消費者實現。它運行幾秒鐘,稍後掛起。任何想法如何解決這個問題。如何解決生產者消費者中的死鎖
import java.util.ArrayDeque;
import java.util.Queue;
public class Prod_consumer {
static Queue<String> q = new ArrayDeque(10);
static class Producer implements Runnable {
public void run() {
while (true) {
if (q.size() == 10) {
synchronized (q) {
try {
System.out.println("Q is full so waiting");
q.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
synchronized (q) {
String st = System.currentTimeMillis() + "";
q.add(st);
q.notifyAll();
}
}
}
}
static class Consumer implements Runnable {
public void run() {
while (true) {
if (q.isEmpty()) {
synchronized(q) {
try {
System.out.println("Q is empty so waiting ");
q.wait();
}catch(InterruptedException ie) {
ie.printStackTrace();
}
}
}
synchronized(q) {
System.out.println(q.remove());
q.notifyAll();
}
}
}
}
public static void main(String args[]) {
Thread consumer = new Thread(new Consumer());
Thread consumer2 = new Thread(new Consumer());
Thread producer = new Thread(new Producer());
producer.start();
consumer.start();
consumer2.start();
}
}
一個小問題,我想提出。通常當一個線程等待時,它會放棄它獲取的相應的監視器,直到有人通知。一旦它從等待()中醒來,線程將已經獲得監視器。然而,你的方法是放棄獲得的監視器(通過離開同步塊)並再次獲取,這仍然有效(從我可以識別的),但增加了額外的不必要的負擔。 –
@AdrianShum - 你注意到這個問題是對的。如果有多個生產者線程或消費者線程,那麼離開'synchronized'塊會給每個線程一個使用隊列的機會。如果'while'塊被帶入'synchronized'塊中,那麼一旦生產者或消費者獲得了監控器,它就會保持它,直到隊列處於容量或清空狀態(如適用)。如果這是所需的行爲,那麼反轉嵌套順序將是適當的。 –
即使在同步塊中移動循環,它也不會「在顯示隊列處於容量或清空狀態之前保持顯示器」。一旦進入wait(),監視器被釋放,其他線程仍然可以「使用隊列」。唯一的區別是釋放和重新獲取顯示器的開銷。 –