2016-11-20 72 views
0

我有許多生產者,不同類型的生產者/消費者對象,例如ProducerOfX,ProducerOfY,ConsumerOfX,ConsumerOfY。生產者將一個對象(X或Y)放入隊列中,並通知其相關消費者(ProducerOfX僅通知ConsumerOfX)。生產者消費者 - 要鎖定什麼

爲了這個工作,我需要一個對象用作鎖。我的問題是,我是否創建了一個對象,例如新的X()並獲得ProducerOfX和ConsumerOfX來調用wait/notify?

將只有一個隊列,我寫它來保存通用對象MyQueue。所以,許多生產者和消費者都會分享這個隊列說X和Y的對象放在單個隊列中。如果有一個X,ConsumerOfX會被喚醒並刪除X.與Y相同。

我想知道最好是隊列通知消費者'我現在有一個X對象'還是更適合製作者說'嗨,X的消費者,我只是把X放在隊列中'。我猜測隊列的生產者不應該知道隊列的消費者。

有沒有更乾淨的方法來做到這一點?

+0

通常情況下,您使用併發隊列實現來處理鎖定(安全發佈,實際上)以及事物的通知方面。 – BeeOnRope

+0

我試圖進行的任務是教我多線程,因此我沒有使用併發包中的任何東西。 – TheCoder

+0

你的問題不清楚。如果您有不同的對象類型和不同的使用者,請使用兩個隊列。也許你應該把問題分解成至少兩個問題:一個側重於如何構建一個併發隊列,另一個是關於讓不同的生產者/消費者類型與一個隊列交互的想法。他們似乎與我正交。 – BeeOnRope

回答

0

這取決於實施。如果不同產品有單獨的隊列,則每個隊列必須使用單獨的鎖對象(此鎖對象可能是隊列本身)進行保護。

另外它取決於你是否正在編寫隊列的實現,那麼你可能會決定把Lock對象作爲一個私有變量。另外,您可以檢查隊列是否已滿,您可能會選擇在專用鎖變量上使用wait。一旦消耗了任何對象,就可以在私有鎖對象上調用notifyall(或notify,儘管notifyall是可取的)。類似的,如果消費者調用方法在隊列爲空時從隊列中提取元素,則可以使用waitnotify邏輯。這樣你的隊列類將負責使用私有變量對象進行鎖定和通知。由於隊列具有私有變量lovk對象,因此每個隊列實例都有自己獨立的Lock對象。

其他方式是,如果隊列是通用隊列,可能不是你正在編寫隊列,那麼你需要保護調用添加和讀取方法的代碼。如果你爲不同的產品(x,y等)分開排隊,那麼你需要爲每個隊列使用不同的Lock對象。這是防止死鎖所必需的,它可能發生(如果我們沒有sepatrate鎖對象),consumerX正在等待queueX插入一個元素(因爲它是空的),而另一個producerY沒有機會插入queueY(因爲它的充分)。因此你需要單獨的鎖定對象。

更新

@TheCoder如果只有一個生產者和消費者在同類型產品中都intrested那麼一個隊列就可以了。現在來了兩個應該交流的共享對象的問題。這取決於實現,如果你希望Queue處理它,Queue可以有一個私人字段private Object monitor = new Object();,並且可以使enqueuedequeue方法在`monitor'上同步。

dequeue方法如果隊列爲空,則在while循環內調用monitor.wait(),直到隊列爲空。如果隊列不爲空,則從隊列中刪除對象並調用monitor.notifyAll();

enqueue如果隊列已滿,則調用monitor.wait()中的while循環直到隊列滿。如果隊列是不是滿的,則在隊列中添加一個對象,然後調用monitor.notifyAll();

如果你的實現是這樣的,你想排隊不照顧同步化的,那麼你應該有一個共同的目標上ProducrerConsumer可以調用enqueue之前同步和dequeuequeue。這個共享對象可以是queue本身的實例。將需要在共享對象的同步塊內調用waitnotifyAll

+0

一個隊列。看我的編輯。 – TheCoder

+0

各個消費者和生產者之間共享一個隊列。好吧現在你有不同的消費者用於不同的產品還是消費者,生產者也是通用的(任何消費者都可以消費產品X,任何生產者都可以生產Y)? –

+0

擁有單個隊列可能不是一個好主意,它可能發生在特定產品的生產者從不或很少有機會產生。對於特定產品的消費者可能會發生同樣的情況...... –