80

我正在学习CopyOnWriteArrayList类。

  • 复制新数组的目的是什么?
  • 是其他线程读取数组吗?

所以如果系统并发高,大部分线程的动作都是读而不是写,最好使用CopyOnWriteArrayList.

4

2 回答 2

99

如此链接所述:

CopyOnWriteArrayList是 Java 5 并发 API 中引入的并发 Collection 类,以及它ConcurrentHashMap在 Java 中流行的表亲。

CopyOnWriteArrayList实现 List 接口ArrayListVectorLinkedList它是一个线程安全的集合,它以与 Vector 或其他线程安全集合类略有不同的方式实现其线程安全。

顾名思义,CopyOnWriteArrayList 使用每个突变操作(例如添加或设置)创建底层 ArrayList 的副本。通常 CopyOnWriteArrayList 非常昂贵,因为它涉及每次写入操作的昂贵 Array 复制,但如果您有一个迭代次数超过突变的列表,例如您主要需要迭代 ArrayList 并且不要经常修改它,那么它非常有效。

CopyOnWriteArrayList 的迭代器是故障安全的,即使在迭代开始后修改了底层 CopyOnWriteArrayList也不会抛出 ConcurrentModificationException ,因为迭代器正在对 ArrayList 的单独副本进行操作。因此,对 CopyOnWriteArrayList 所做的所有更新对 Iterator 均不可用。

要获得最新版本,请重新阅读list.iterator();

话虽如此,大量更新此集合会降低性能。如果您尝试对 a 进行排序,CopyOnWriteArrayList您会看到列表抛出一个UnsupportedOperationException(排序调用集合上的集合 N 次)。仅当您进行超过 90% 的读取时才应使用此读取。

于 2013-07-25T08:48:25.927 回答
28

应对新阵列的目的是什么?

复制底层数组可确保数据结构的任何迭代都是安全的,因为迭代发生在数据的基本不可变“快照”上。

是其他线程读取数组吗?

有点。更具体地说,每个线程都能够安全地迭代数组,而不必担心ConcurrentModificationException或其他未知/未定义的行为。

所以如果一个系统是高并发的,大部分线程的动作都是读而不是写,最好使用CopyOnWriteArrayList。我对吗?

不。只有当大多数线程的操作是列表上的迭代时。如果大多数活动都是基于随机访问的读取,aReadWriteLock可能会更好。

来自 javadocCopyOnWriteArrayList

这通常成本太高,但当遍历操作的数量大大超过突变时,它可能比替代方法更有效,并且在您不能或不想同步遍历但需要排除并发线程之间的干扰时很有用。

于 2013-07-25T08:54:50.120 回答