2016-01-08 41 views
2

假設我有ConcurrentLinkedQueue類型的類領域。這個類的一些方法正在爲這個隊列提供新的元素。而其他一些方法需要輪詢隊列內的所有元素,在這個時刻爪哇 - 的ConcurrentLinkedQueue - 民意調查所有

我不能循環使用poll(),因爲有一個機會,有些元素可能被提供給此隊列while循環還沒有完成。如果新元素的提供速度比我對它們的要求更高,我認爲它甚至可能是一個無限循環。所以我需要某種pollAll()

有沒有一種方法,我可以做到這一點?也許有一個適合這個的集合?

回答

2

如果您可以更改您的應用程序以使用BlockingQueue實現之一,則有一種方法drainTo,它似乎完全符合您的要求。它刪除隊列的當前內容並將它們傳送到目標集合。

有各種各樣的BlockingQueue實現;他們應該都是線程安全的。奇怪的是,沒有指定drainTo是原子的,儘管它在我檢查的實現中(ArrayBlockingQueueLinkedBlockingQueue)。

+0

正是我在找什麼,謝謝! – coolguy

1

好像你需要某種形式的「暫停」的時刻。一種做法:

AbstractQueue<Object> queue = new ConcurrentLinkedQueue<>(); 
    int size = queue.size(); 

    for (int i = 0; i < size; i++) { 
     Object object = queue.poll(); 
     if (object == null) { 
      // Collection has shronk break 
      break; 
     } 
     // Do processing here 
    } 

通過將大小存儲到局部變量中,大小不會改變,您可以使用該大小的元素進行處理。如果在過程元素添加期間,它將不會受到無限循環的影響。

UPDATE:該.iterator()可能是更好的比我的第一個例子使用:

返回的Iterator是一個「弱一致」的迭代器, 不會拋出ConcurrentModificationException,並且確保 遍歷元件,因爲它們迭代器構造時的存在, 和可以(但不保證)反映任何修改 後續施工。

UPDATE 2:這是將採取的所有元素也被刪除的一次並對其進行處理的方法。

 AbstractQueue<Object> queue = new ConcurrentLinkedQueue<>(); 
     queue.add("Test1"); 
     queue.add("Test2"); 
     queue.add("Test3"); 

     Object[] objList = queue.toArray(); 

     queue.remove("Test2"); 

     for (Object obj : objList) { 
      // Make sure you delete it, because we don't use .poll 
      // Put it at top, to reproduce the poll as much as possible 
      queue.remove(obj); 

      // Do processing 
     } 

這將輸出:

Test1 
Test2 
Test3 

因爲拷貝到新objList[]它也將顯示 「Test2的」。如果將重複項添加到列表中,此示例可能會導致.remove()方法出現問題。因爲如果添加的元素與.remove()中的對象重複,那麼該對象會立即被刪除。

另外請注意,這種方法比較慢,因爲.remove()需要遍歷元素來找到它O(N1),其中.poll是即時O(1)。

+0

它可以是一個選項。但是如果有人在以這種方式迭代隊列時刪除元素呢?從這裏獲得保護會很好 - 閱讀已刪除的元素,例如他們仍然存在。也許有一種方法可以在目前的情況下「複製」隊列?不幸的是'ConcurrentLinkedQueue'沒有實現'Cloneable' – coolguy

+0

@coolguy你有一個有效的觀點。我更新了這個問題。在這種情況下,在收集收縮的情況下,應該驗證'poll'的結果。正如文檔中所述'檢索,但不刪除此隊列的頭部,或者如果此隊列爲空,則返回null'。所以'null'你確定這個集合是空的。 –

+0

不幸的是,仍然有機會處理錯誤的元素。假設這個隊列有5個刪除和10個添加,而循環正在運行。我不會處理這5個被刪除的元素(但是我想),並且我將處理在啓動循環後添加的5個元素(並且我不想處理它們)。 如果不會有其他選擇,我會照你所描述的做,但我希望有更適合的東西 – coolguy