CopyOnWriteArrayList在什么情况下是合适的?

2022-08-31 12:31:02

我正在学习CopyOnWriteArrayList类。

  • 复制新阵列的目的是什么?
  • 是否让其他线程读取数组?

因此,如果系统具有高并发性,并且大多数线程的操作都是读取而不是写入,则最好使用 。CopyOnWriteArrayList


答案 1

如此链接所述:

CopyOnWriteArrayList是Java 5 Concurrency API中引入的并发集合类,以及Java中流行的表亲。ConcurrentHashMap

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

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

CopyOnWriteArrayList 的迭代器是故障安全的,并且不会抛出 ConcurrentModificationException,即使底层的 CopyOnWriteArrayList 在迭代开始后被修改,因为 Iterator 正在对 ArrayList 的单独副本进行操作。因此,在CopyOnWriteArrayList上进行的所有更新都不适用于迭代器。

要获得最新版本,请像这样进行新的阅读list.iterator();

话虽如此,经常更新此集合会扼杀性能。如果您尝试对 a 进行排序,您将看到列表抛出一个(排序调用集合 N 次上设置的)。仅当执行超过 90% 的读取时,才应使用此读取。CopyOnWriteArrayListUnsupportedOperationException


答案 2

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

复制基础数组可以保证数据结构的任何迭代都是安全的,因为迭代是在数据基本上不可变的“快照”上进行的。

是否让其他线程读取数组?

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

因此,如果系统具有高并发性,并且大多数线程的操作都是读取而不是写入,则最好使用CopyOnWriteArrayList。我说的对吗?

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

从 javadoc 的CopyOnWriteArrayList

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