2

据我所知,当一个线程迭代集合而另一个线程修改集合时,有两种方法可以避免 ConcurrentModificationException。

  1. 客户端锁定,基本上在迭代期间锁定集合。需要访问集合的其他线程将阻塞,直到迭代完成。
  2. 克隆集合并迭代副本的“线程受限”。

我想知道还有其他选择吗?因为第一种方式显然是不可取的并且性能不佳,如果集合很大,其他线程可能会等待很长时间。第二种方式我不确定,因为我们克隆了集合,并迭代了副本,所以如果其他线程进来并修改原始的,那么复制的就会变得陈旧,对吧?这是否意味着我们需要通过克隆重新启动并在修改后再次迭代它?

4

2 回答 2

7

我想知道还有其他选择吗?

使用不会引发此异常的并发集合之一。相反,它们提供了弱一致性。即,添加或删除元素可能会在迭代时出现,也可能不会出现。

http://docs.oracle.com/javase/tutorial/essential/concurrency/collections.html

java.util.concurrent 包包括许多对 Java 集合框架的补充。这些最容易通过提供的集合接口进行分类:

  • BlockingQueue 定义了一个先进先出数据结构,当您尝试添加到满队列或从空队列中检索时,该数据结构会阻塞或超时。
  • ConcurrentMap 是 java.util.Map 的子接口,它定义了有用的原子操作。这些操作仅在键存在时删除或替换键值对,或仅在键不存在时添加键值对。使这些操作原子化有助于避免同步。ConcurrentMap 的标准通用实现是 ConcurrentHashMap,它是 HashMap 的并发模拟。
  • ConcurrentNavigableMap 是 ConcurrentMap 的子接口,支持近似匹配。ConcurrentNavigableMap 的标准通用实现是 ConcurrentSkipListMap,它是 TreeMap 的并发模拟。
于 2012-12-17T15:44:30.237 回答
0

您可以使用java.util.Concurrent 中的类,例如CopyOnWriteArrayList

于 2012-12-17T15:43:36.090 回答