我的线程池具有固定数量的线程。这些线程需要频繁地从共享列表中写入和读取。
那么,java.util.concurrent
在这种情况下,包中的哪种数据结构(最好是一个列表,必须没有监视器)是最好的?
ConcurrentModificationException
可能不是来自一个同步的问题; 例如,它还会在集合上的for循环中出现,您尝试从集合中删除元素。
Vector
吗?
我的线程池具有固定数量的线程。这些线程需要频繁地从共享列表中写入和读取。
那么,java.util.concurrent
在这种情况下,包中的哪种数据结构(最好是一个列表,必须没有监视器)是最好的?
ConcurrentModificationException
可能不是来自一个同步的问题; 例如,它还会在集合上的for循环中出现,您尝试从集合中删除元素。
Vector
吗?
Answers:
最好是
List
该只 List
实施java.util.concurrent
是的CopyOnWriteArrayList。正如Travis Webb所提到的,还有一个同步列表选项。
就是说,您确定要成为一个List
吗?并发Queue
s和Map
s 有更多选择(您可以Set
从Map
s生成s),对于要使用共享数据结构执行的许多类型的操作,这些结构往往最有意义。
对于队列,您有很多选择,最合适的选择取决于您使用它的方式:
CopyOnWriteArrayList
缺点是写操作非常昂贵(但读操作便宜)。如果要进行大量写操作,则最好使用同步列表或队列。
可以使任何Java集合都是线程安全的,如下所示:
List newList = Collections.synchronizedList(oldList);
或创建一个全新的线程安全列表:
List newList = Collections.synchronizedList(new ArrayList());
ConcurrentHashMap
即使有Collections.synchronizedMap
方法,也有一个。
ConcurrentHashMap
。同步实现的细节不同。使用中的synchronized
方法Collections
基本上只是将类包装在Java监视器中。ConcurrentHashMap
使用更巧妙的并发功能。
如果列表大小固定,则可以使用AtomicReferenceArray。这将允许您对插槽执行索引更新。您可以根据需要编写一个列表视图。
您可能想看看Doug Lea根据Paul Martin的“实用的无锁双链表”编写的ConcurrentDoublyLinkedList。它没有实现java.util.List接口,但是提供了您将在List中使用的大多数方法。
根据javadoc:
Deque(双端队列)的并发链接列表实现。并发插入,删除和访问操作可在多个线程之间安全地执行。迭代器是 弱一致性的,返回元素反映了创建迭代器时或创建迭代器后的双端队列状态。它们不会引发ConcurrentModificationException,并且可以与其他操作并发进行。
ConcurrentLinkedQueue
使用无锁队列(基于较新的CAS指令)。
List
接口。
List.set(int index, Object element)
使用ConcurrentLinkedQueue 实施?
List
特定于-的方法要么无法使用Queue
(例如,在特定索引处添加/设置)无法实现,要么可以被实施,但效率不高(从索引获取)。所以我认为您无法真正包装它。就是说,我认为关于a的建议Queue
很好,因为OP并未真正解释他们为什么需要a List
。
如果设置足够,则可以使用ConcurrentSkipListSet。(其实现基于ConcurrentSkipListMap,该实现实现了跳过列表。)
包含,添加和删除操作的预期平均时间成本为log(n)。size方法不是恒定时间操作。
List
。