2011-03-23 110 views
3

我試圖想通過在一個Java應用程序的一些設計中關於內存分配和多線程,這就是我想知道:返回Java中的數組VS集合

我有了一個同步集合類說一個列表,幾秒鐘更新一次,但所有的更新都是在類和它自己的線程中發生,而不是從其他線程中發生。不過,我有很多其他線程調用getCollection()方法,並執行foreach以只讀方式迭代其內容。這是我不知道:

如果另一個線程迭代同步總彙將執行更新的單個線程必須等待,直到時間點沒有其他線程迭代?

我的第二個問題是,通過執行.toArray返回集合的數組副本而不是集合本身似乎是有意義的,但是從內存的角度考慮它並不需要分配新的數組那就是每次收集內容的大小,並且如果每秒鐘在具有數千個對象的集合上每秒調用數百次是我不知道的事情。

另外,如果我從來沒有返回集合本身不是使同步列表不再是必要的?

希望得到任何輸入。謝謝! - 鄧肯

回答

6

我會建議你使用的CopyOnWriteArrayList。這是線程安全的,可以通過任意數量的線程高效讀取。只要你有少量的更新,這應該沒問題。

但是,爲了回答你的問題。如果您在修改同步集合時對迭代器進行迭代,您將得到一個ConcurrentModificationException(COWAL不會得到此結果)您的更新不會被此阻塞,只有您的讀者會遇到問題。

每次調用getCollection時,都會創建一個副本,而不是在每次修改集合時創建一個副本(更少發生)這是COWAL爲您做的。

如果按需返回副本,則仍需要同步集合。

10

如果另一個線程迭代 同步總彙將單 線程執行更新有 要等到時間點沒有 其他線程迭代?

如果你在談論同步(不是併發)集合,那麼是的。 至於第二個問題,它 看起來像一個真正的用例java.util.concurrent.CopyOnWriteArrayList

+0

+1:對我來說太快了。 ;) – 2011-03-23 19:04:15

2

處理此問題的最簡單方法可能是保留兩個集合:一個由類本身進行更新,另一個是在調用getCollection()時返回的易失性字段中的只讀副本。

後者需要在適當時更新主集合的過程來重新創建。這允許你原子地更新你的集合:一次改變幾個元素,同時隱藏中間狀態。

如果您的更新不頻繁,並且每次更新都使集合保持一致狀態,則使用已經建議的CopyOnWriteArrayList。

0

似乎頻繁更新集合,並頻繁調用#getCollection()。您可以使用CopyOnWriteArrayList,但每次修改數組時都會創建一個副本。所以你需要看看這是如何影響性能的。

另一種選擇是任務類中的線程在每次調用#getCollection時複製一份。這將涉及#getCollection等待內部類線程完成。

如果您只是希望#getCollection返回最近的副本而不是最新的副本,那麼您可以讓內部線程定期創建在#getCollection中返回的集合的副本。該副本將需要變化或成爲AtomicReference。