我的线程池有固定数量的线程。这些线程需要经常从共享列表中写和读取。
那么,在这种情况下,java.util.concurrent
包中哪个数据结构(最好是List,必须是无监视器)最好?
答案 0 :(得分:76)
最好是
List
List
中的仅 java.util.concurrent
实施是CopyOnWriteArrayList。 Travis Webb提到了同步列表的选项。
那就是说,你确定你需要它成为List
吗?并发Queue
和Map
的选项还有很多(你可以从Set
生成Map
s,这些结构往往最有意义对于您想要使用共享数据结构执行的许多类型的事情。
对于队列,您有大量选项,哪些最合适取决于您需要如何使用它:
答案 1 :(得分:51)
任何Java集合都可以像以下那样是线程安全的:
List newList = Collections.synchronizedList(oldList);
或者创建一个全新的线程安全列表:
List newList = Collections.synchronizedList(new ArrayList());
答案 2 :(得分:7)
如果列表的大小固定,那么您可以使用AtomicReferenceArray。这将允许您对插槽执行索引更新。如果需要,您可以编写列表视图。
答案 3 :(得分:6)
你可能想看看Doug Lea根据Paul Martin的#34; A Practical Lock-Free Doubly-Linked List"撰写的ConcurrentDoublyLinkedList。它没有实现java.util.List接口,但提供了在List中使用的大多数方法。
根据javadoc:
Deque的并发链表实现 (双端队列)。并发插入,删除和访问 操作跨多个线程安全执行。迭代器是 弱一致,返回反映状态的元素 在迭代器创建时或之后的某个时刻的双端队列。他们 不抛出ConcurrentModificationException,并且可能 与其他行动同时进行。
答案 4 :(得分:3)
ConcurrentLinkedQueue
使用无锁队列(基于较新的CAS instruction)。
答案 5 :(得分:1)
如果设置足够,可能会使用ConcurrentSkipListSet。 (它的实现基于ConcurrentSkipListMap,它实现了skip list。)
预期的平均时间成本是包含,添加和删除操作的log(n); size方法不是恒定时间操作。