7

我的代码抛出以下异常:

java.util.ConcurrentModificationException
        at java.util.LinkedList$ListItr.checkForComodification(LinkedList.java:761)
        at java.util.LinkedList$ListItr.next(LinkedList.java:696)
        at java.util.AbstractCollection.addAll(AbstractCollection.java:305)
        at java.util.LinkedHashSet.<init>(LinkedHashSet.java:152)
        ...

我想要ConcurrentLinkedHashSet修复它,

但我只发现ConcurrentSkipListSetjava.util.concurrent这是TreeSet,不是LinkedHashSet

进入JDK6.0的任何简单方法ConcurrentLinkedHashSet

感谢帮助 :)

4

4 回答 4

10

ConcurrentModificationException 与您正在考虑的形式的并发无关。这只是意味着在迭代集合时,有人(可能是您自己的代码 - 这种情况经常发生;))正在更改它,即添加/删除一些值。

确保您使用迭代器从集合中移除值,而不是集合本身。

编辑:如果真的另一个线程同时访问集合,那么您从标准库获得的弱同步无论如何都是无用的,因为您必须在整个操作期间阻止集合,而不仅仅是一个添加/消除!即类似的东西

synchronize(collection) {
   // do stuff here
}
于 2011-03-13T17:06:33.023 回答
4

您始终可以使用Collections.synchronizedMap(myMap);. 但是,在您迭代时尝试更改地图(我假设这是您的错误的原因)仍然是一个问题。

来自 synchronizedMap 的文档:

返回由指定映射支持的同步(线程安全)映射。为了保证串行访问,对支持映射的所有访问都是通过返回的映射完成的,这一点至关重要。

当迭代其任何集合视图时,用户必须在返回的地图上手动同步......不遵循此建议可能会导致不确定的行为。

这是因为

  • 通常并发集合确实保证了原子获取/放置,但在迭代期间不会锁定整个集合,这太慢了。迭代没有并发保证,这实际上是针对映射的许多操作。

  • 如果您在迭代期间进行更改,这并不是真正的并发,因为不可能确定正确的行为 - 例如,您如何协调返回 hasNext == true 的迭代器与从集合中删除 a (可能是下一个值)?

于 2011-03-13T16:57:43.583 回答
2

有 ConcurrentLinkedHashMap - https://code.google.com/p/concurrentlinkedhashmap/

您可以使用 java.util.Collections.newSetFromMap(map) 从中创建 Set

于 2013-12-13T10:50:06.627 回答
0

不幸的是没有。您可以实现自己的,包装 ConcurrentHashMap 和 ConcurrentLinkedQueue,但这不允许您轻松删除值(删除将是 O(N),因为您必须遍历队列中的所有内容)...

不过,您使用 LinkedHashSet 是为了什么?或许可以提出替代方案...

于 2011-03-13T16:54:29.183 回答