是否有一个实现List接口的容器在迭代时支持并发修改?具体来说,我希望一个线程迭代集合,而许多线程插入并从此列表中删除元素。迭代器应该看到它尚未遍历的列表的修改。
我正在寻找类似于ConcurrentLinkedQueue的迭代行为,但支持在特定索引处添加和删除元素。最好是我正在寻找强一致性(我愿意为它支付锁争用开销)但我可能生活在弱一致性。
我很高兴看到第三方库,因为我在标准库中看不到任何可以提供我正在寻找的东西。
答案 0 :(得分:5)
有一些接近的东西。它被称为CopyOnWriteArrayList
- 尽管有一个限制,即迭代器在迭代时不会看到所做的更改,而是继续迭代迭代开始时的集合。
该集合在写入时速度很慢(但读取速度很快),这是另一回事。
jME3有一个名为SafeArrayList
doc here的内部集合,它更快但不支持多线程访问。它确实支持从迭代器等访问(因此你可以循环遍历列表中的对象并同时添加/删除它们,只要你不尝试从多个线程执行此操作)。同样,迭代器在迭代时不会看到所做的更改,它们将继续迭代原始数据。
并发包提供了许多其他可能有用的数据结构。
另一种方法是在列表中使用标准ArrayList
,synchronize
进行修改和读取,然后使用索引对其进行迭代。 (即list.get(i)
)。
但是会有很多边缘情况。例如,如果你删除一个元素,它会将所有其他元素向下移动,这样你就可以跳过那个点之后的任何迭代器。
实际上,您最终可能需要保留迭代器列表,并在添加/删除元素时循环遍历迭代器列表并相应地更新其位置!
答案 1 :(得分:0)
单独使用Java API,您可以使用Collections.synchronizedList()
获取同步列表。检查方法的规格是否符合您的使用要求。并且,使用ListIterator
(使用List.listIterator()
方法获得)来迭代和修改列表。