2011-05-20 66 views
12

我有一個ArrayList將被緩存和無限期地在多個線程之間共享。操作包括頻繁添加和刪除,以及偶爾迭代它。替代CopyOnWriteArrayList頻繁寫入,偶爾迭代

ArrayList生活在管理訪問它的包裝類:

public class MyListWrapper<T> implements Iterable<T> { 

    private List<T> innerList = new ArrayList<T>(); 

    public Iterator<T> iterator() { 
     return innerList.listIterator(); 
    } 

    public void add(T element) { 
     innerList.add(element); 
     //app-specific logic 
    } 

    //remove(T), etc in the same pattern... 
} 

我目前正在線程安全的準備工作。起初,CopyOnWriteArrayList看起來是最好的答案,但其表現令我擔憂,因爲修改將比其他任何事情更頻繁。

會手動更改包裝類,如這是一個更好的選擇?:

public Iterator<T> iterator() { 
    return new ArrayList<T>(innerList).listIterator(); 
} 

//plus concurrency tweaks for any non-atomic modifications to innerList 

請幫我找到最好的方法。

回答

7

你可以嘗試使用一個Collections.newSetFromMap(new ConcurrentHashMap<T, Boolean>());這將給你一個併發散列集,它會給你附近的O(1)添加和刪除。

+0

非常好,這正是我所需要的。 +1教我一些事情。謝謝 – 2011-05-20 15:46:39

+0

它的迭代器是線程安全的,所以你不需要同步並且可能不需要拷貝。 – 2011-05-20 16:45:49

+0

在java 1.8中我猜這個方法已經被重命名爲Collections.newSetFromMap – 2017-02-08 03:31:58

4

如果您可以使用隊列接口而不是列表,則可能會使用ConcurrentLinkedQueue。我會爭辯說,比預期更多的用例可能會滿足隊列。 List的一個關鍵優勢是隨機訪問(基於索引),但在併發情況下,隨機訪問既不必要也不需要。

ConcurrentLinkedQueue是一個很好的隊列併發實現。

+0

+1自從問這個問題後,我意識到隨機訪問是不重要的,並且沒有必要首先使用List。 – 2011-05-20 18:28:35