2011-03-08 62 views

回答

0

您可以覆蓋任何實施BlockingQueue<T>的add和put方法,以首先檢查元素是否已經在隊列中,例如,

@Override 
public boolean add(T elem) { 
    if (contains(elem)) 
     return true; 
    return super.add(elem); 
} 
+0

好的,但不是最優的,因爲正常的BlockingQueue實現包含的()要求整個隊列 – 2011-03-08 19:56:48

+0

的遍歷,我會說:「最佳」是主觀的。除非你自己推出,否則其他簡單的選項就是秒殺建議的選項,這是一個經典的空間與時間的折衷。所以雖然任何一個都可以被認爲是最好的解決方案,但依靠它的用途,我會因爲它的簡單性而投票贊成。 – 2011-03-08 21:03:27

+7

如果「最優」包含正確的,那麼這個實現會失敗,因爲它是一個競爭條件。 – jtahlborn 2012-11-21 15:57:37

4

您可以創建一個組成BlockingQueue,Set和鎖的新類。當你把()你測試對照集合,同時拿着防止get()運行的鎖。當你得到()時,你從該集合中刪除該項目,以便它可以在將來再次放置()。

-2
class BlockingSet extends ArrayBlockingQueue<E> { 
    /*Retain all other methods except put*/ 
    public void put(E o) throws InterruptedException { 
     if (!this.contains(o)){ 
     super.put(o); 
     } 
    } 
} 
+0

'contains'的實現遍歷列表,這會很慢... – 2013-04-12 13:23:48

1

通過用於預知迭代順序和一定的時間增加,刪除和鏈接哈希set支持一種阻塞隊列實現包含操作:

There you go

+0

感覺非常慢。 – horec 2015-12-14 10:09:29

+0

@horec - 這種感覺來自於看代碼還是來自實際嘗試呢?看着他的代碼,我有同樣的擔憂,但還沒有真正給它一杆尚未 – forhas 2016-01-05 08:48:19

+0

您的鏈接已經死了:-( – rcomblen 2017-05-30 09:55:59

1

我寫了這個類來解決類似的問題:

/** 
* Linked blocking queue with {@link #add(Object)} method, which adds only element, that is not already in the queue. 
*/ 
public class SetBlockingQueue<T> extends LinkedBlockingQueue<T> { 

    private Set<T> set = Collections.newSetFromMap(new ConcurrentHashMap<>()); 

    /** 
    * Add only element, that is not already enqueued. 
    * The method is synchronized, so that the duplicate elements can't get in during race condition. 
    * @param t object to put in 
    * @return true, if the queue was changed, false otherwise 
    */ 
    @Override 
    public synchronized boolean add(T t) { 
     if (set.contains(t)) { 
      return false; 
     } else { 
      set.add(t); 
      return super.add(t); 
     } 
    } 

    /** 
    * Takes the element from the queue. 
    * Note that no synchronization with {@link #add(Object)} is here, as we don't care about the element staying in the set longer needed. 
    * @return taken element 
    * @throws InterruptedException 
    */ 
    @Override 
    public T take() throws InterruptedException { 
     T t = super.take(); 
     set.remove(t); 
     return t; 
    } 
}