2014-03-05 51 views
1

我有一個生產者/消費者用例,這是一個有點不尋常。 我有一些真正的世界用例,我希望他們能夠在不阻塞的情況下將對象添加到集合中。 消費者(只有一個)應該阻塞,直到集合中有一定數量的對象可用(例如500),然後大量消費它們。雖然少於500個,它應該阻止並等待收集填充。我不介意隊列超過這個值(700,1000等)很短的時間。生產者/消費者 - 生產者增加了數據收集不阻塞,從消費者的消費收集數據批量

我目前似乎還沒有找到一個解決方案來解決這個確切的問題。 我在考慮使用ConcurrentLinkedQueue並讓消費者定期檢查隊列是否有足夠的數據,但這似乎相當起反作用。

另一個想法是使用LinkedBlockingQueue。生產者不會阻塞(除非隊列已滿,這意味着它具有Integer.MAX_VALUE值 - 這不是我的情況,所以它都很好)。消費者將執行queue.take()並將元素添加到內部集合中。當內部收集達到500個元素時,它將批量使用它們。

您有任何提示嗎?

謝謝!

回答

2

最後我去了LinkedBlockingQueue。

生產者將項目添加到隊列中。

消費者將做queue.poll(),並保持物品進入內部集合。當內部收集達到500個元素時,它將大量消耗它們。我也可以設置一些超時。例如,如果X秒過去了,即使它的項目數少於所需的數量(例如220),我也會使用該集合。

+0

你爲什麼不決定生產批次?只是好奇什麼是最好的類似的用例。 – wikier

1

你可以簡單地引入一箇中間隊列和消費/製造商,這將得到由生產者充滿了隊列中的項目,將它們存儲在一個列表,一旦列表大小是500,放列表本身在隊列由消費者閱讀。消費者會阻止下一個有500件物品的清單。

當然你也可以封裝這個邏輯由生產者共享的對象中:生產者自己的項目添加到「配料機」的對象。批處理對象將項目添加到專用列表中,一旦列表大小爲500,批處理將該列表添加到隊列中。只要確保batcher的addItem()方法是同步的。這將避免額外的線程和隊列。

+0

如果批量化的的addItem()是同步的它會創建誰想要在同一時間添加對象的生產瓶頸,是否正確?這將打敗我的目的:「製作者無阻礙地向收藏添加數據」。如果分配器將列表添加到隊列中,則消費者將逐一接收隊列中的這些項目 - 這不是我們想要的,我們希望它一次接收500個。如果Batcher爲生產者準備了一個隊列,並且當隊列中包含500個元素將其排入列表並將其傳遞給消費者時,情況會不會更好? –

+0

將項目添加到共享隊列還涉及同步:隊列必須保持其完整性。批處理器的addItem()方法將增加一個非常小的開銷:將一個項目添加到預先分配的ArrayList 500,檢查其大小,如果是500,則將addAll()添加到隊列並清除列表。我不會認爲這個小開銷在嘗試之前就構成了一個瓶頸,並且看它是否可行。畢竟,如果你有一個消費者有N個生產者,那麼生產者就不能高速生產,因此爭奪配料鎖的機會就會減少。 –

+0

並重新閱讀我的答案:批處理器將500個項目列表添加到隊列中。消費者阻塞,直到隊列中有500個列表可用。也就是說,分配給消費者也是可能的。但如果你改變主意並引入額外的消費者,它將不再容易工作。 –