这取决于您要如何限制并发。最简单的方法可能是使用
CopyOnWriteArrayList。当您从中获取一个迭代器时,该迭代器将反映
该列表在创建迭代器时的外观 - 迭代器 将看不到后续修改。好处是它可以应付很多争用,缺点是添加新项相当昂贵。
另一种方法是锁定,最简单的方法可能是将列表包装在一起
Collections.synchronizedList并在迭代时在列表上进行同步。
第三种方法是使用某种形式
BlockingQueue并将新元素提供给工人。
编辑:
正如OP所述,仅需要快照,
CopyOnWriteArrayList这可能是最好的即用型替代方法。一种替代方法(用于廉价添加,但阅读成本较高)是仅
synchronizedList在需要遍历时创建副本(读取时复制而不是写入时复制):
List<Foo> originalList = Collections.synchronizedList(new ArrayList());public void mainThread() { while(true) originalList.add(getSomething());}public void workerThread() { while(true) { List<Foo> copiedList; synchronized (originalList) { copiedList = originalList.add(something); } for (Foo f : copiedList) process(f); }}编辑: 考虑一下,读取时复制的版本可以简化一些以避免所有
synchronized块:
List<Foo> originalList = Collections.synchronizedList(new ArrayList());public void mainThread() { while(true) originalList.add(getSomething());}public void workerThread() { while(true) { for (Foo f : originalList.toArray(new Foo[0])) process(f); }}编辑2:
这是一个简单的包装,用于读取时复制列表,它不使用任何帮助程序,并且尝试尽可能细化锁定(我故意使它有些多余,以次优为准,以演示需要锁定的位置):
class CopyOnReadList<T> { private final List<T> items = new ArrayList<T>(); public void add(T item) { synchronized (items) { // Add item while holding the lock. items.add(item); } } public List<T> makeSnapshot() { List<T> copy = new ArrayList<T>(); synchronized (items) { // Make a copy while holding the lock. for (T t : items) copy.add(t); } return copy; }}// Usage:CopyOnReadList<String> stuff = new CopyOnReadList<String>();stuff.add("hello");for (String s : stuff.makeSnapshot()) System.out.println(s);基本上,当您锁定时,您:
- …将项目添加到列表中。
- …遍历列表以制作副本。



