2013-03-04 23 views
0

我發現自己重複這種模式,並經常想知道它是否是Java中的慣用語,或者有更好的方法來實現這種行爲。排空之前的塊ArrayBlockingQueue

問題:給定一個生產者/消費者安裝,消費者要處理項目的批次,因此它使用drainTo(),但是drainTo()將輪詢現有的項目,並可能無法獲得任何物品,以避免這種情況我前綴漏極與一個take()確保它阻塞,直到至少有一個項目可用。

我得到的一個問題是,在一個特定的數據集中,有很多使用案例批量大小通常在(1,N,1,N)之間不規則交替。一般來說,這是解決這個問題的常用方法:

例子:

ArrayBlockingQueue<Foo> queue; 

function void produce() { 
    while(true) { 
     queue.put(createFoo()); 
    } 
} 

function void consumeBatchSpin() { 
    while(true) { 
     List<Foo> batch = Lists.newLinkedList(); 
     queue.drainTo(batch); 

     doSomething(batch); 
     //the problem here is that if nothing is being produced, this loop will spin 
    } 
} 

function void consumeBatchTake() { 
    while(true) { 
     List<Foo> batch = Lists.newLinkedList(); 
     batch.add(queue.take()); //force at least one item to be there 
     queue.drainTo(batch); 

     doSomething(batch); 
    } 
} 
+1

http://stackoverflow.com/a/831861/139010和http://cs.oswego.edu/pipermail/concurrency-interest/2006-July/002901.html所以是的,這似乎是一個不完全 - 常見的解決方案。 – 2013-03-04 00:37:34

回答

1

你有沒有考慮加入列表,並承擔得到整個名單。

我最近發佈了一個here。它正在進行代碼審查here,但我的測試表明它是健壯的。

基本上,當你做一個放置時,你將你的新元素添加到當前列表中。當你做一個得到你得到整個列表,並原子上用新的空白替換它。不需要使用drainTo,也不需要旋轉。