在Java中选择最佳并发列表

在Java中选择最佳并发列表,java,concurrency,Java,Concurrency,我的线程池有固定数量的线程。这些线程需要经常从共享列表中写入和读取 那么,在这种情况下,java.util.concurrent包中的哪个数据结构(最好是一个列表,必须是无监视器的)是最好的?使用无锁队列(基于较新的队列)。任何java集合都可以像这样保证线程安全: List newList=Collections.synchronizedList(oldList) 或者创建一个全新的线程安全列表: List newList=Collections.synchronizedList(newarr

我的线程池有固定数量的线程。这些线程需要经常从共享列表中写入和读取


那么,在这种情况下,
java.util.concurrent
包中的哪个数据结构(最好是一个列表,必须是无监视器的)是最好的?

使用无锁队列(基于较新的队列)。

任何java集合都可以像这样保证线程安全:

List newList=Collections.synchronizedList(oldList)

或者创建一个全新的线程安全列表:

List newList=Collections.synchronizedList(newarraylist())

最好是
列表

java.util.concurrent
中唯一的
列表
实现是。正如特拉维斯·韦伯提到的,还有一个同步列表选项

也就是说,您确定需要它成为一个
列表吗?对于并发
Queue
s和
Map
s,有更多的选项(您可以从
Map
s中创建
Set
s),这些结构往往对您希望使用共享数据结构执行的许多类型的操作最有意义

对于队列,您有大量的选项,最合适的选项取决于您需要如何使用它:

您可能想看看Doug Lea根据Paul Martin的“一个实用的无锁双链接列表”编写的文章。它没有实现java.util.List接口,但提供了在列表中使用的大多数方法

根据javadoc:

Deque的并发链表实现 (双端队列)。并发插入、删除和访问 操作跨多个线程安全执行。迭代器是 弱一致性,返回反映 在迭代器创建时或创建之后的某个点上的deque。他们 不要抛出ConcurrentModificationException,否则可能会 与其他操作同时进行


如果列表的大小是固定的,则可以使用。这将允许您对插槽执行索引更新。如果需要,您可以编写列表视图。

如果设置足够,则可以使用。 (它的实现是基于哪个实现的。)


包含、添加和删除操作的预期平均时间成本为log(n);size方法不是固定时间操作。

这取决于要对集合执行的操作。请参阅(虽然是关于.Net的,但概念是相同的)。您不太可能使用
列表编写正确的线程安全代码。现在,我使用的是CopyOnWriteArrayList,但ConcurrentModificationException异常仍然偶尔引发。请包含有关您对集合所做操作的更多信息,以便人们能够更好地回答,否则这只是猜测。
ConcurrentModificationException
可能不是来自同步问题;例如,在集合上的for循环中,您尝试从集合中删除元素。我知道它不是包的一部分,但有人尝试过
Vector
?…它没有实现
List
interface.eSniff,您将如何实现
List.set(int-index,Object-element)
使用ConcurrentLinkedQueue?大多数特定于
列表的方法要么无法使用
队列实现(例如,在特定索引处添加/设置),要么可以实现,但效率低下(从索引获取)。所以我不认为你真的能把它包起来。也就是说,我认为
队列
的建议很好,因为OP没有真正解释他们为什么需要
列表
@ColinD这就是我想要的答案。CLQ不能包装在列表中有很好的理由。虽然我同意,但不能排除队列接口。❗️ 值得注意的是:“请注意,与大多数集合不同,size方法不是一个常量时间操作。由于这些队列的异步性质,确定当前元素数需要遍历元素。”因此,在java.util.concurrent--Uhm中找不到列表实现,即使有一个Collections.synchronizedMap方法,也有一个
ConcurrentHashMap
方法。请阅读
ConcurrentHashMap
上的Javadocs。同步实现的细节是不同的。使用
Collections
中的
synchronized
方法基本上只是将类包装在Java监视器中
ConcurrentHashMap
使用了更聪明的并发特性。是的。尽管如此,它还是会让你的最后一句话有点无效。如果使用监视器,程序的性能确实很差:-(只需补充一点,在newList上的迭代不是线程安全的。!!
CopyOnWriteArrayList
的缺点是写入成本很高(但读取成本很低)如果要进行大量写操作,最好使用同步列表或队列。为了添加到这个答案中,通常您希望只有在存在更改数据或添加/删除数据的操作时,数据结构才是线程安全的。因此,除非您需要通过某个“集”更改“列表”中的数据方法调用,则唯一的其他操作,即添加/删除操作,可以通过队列数据结构轻松处理(这也是一种最佳实践,当然,除非需要异常)。但它是设置为not list。您不能添加具有相同hashcod emultiple的对象。这就是为什么我写道:“如果设置足够…”