在什么情况下CopyOnWriteArrayList适合?
我正在学习CopyOnWriteArrayList类。
- 复制新arrays的目的是什么?
- 是否为其他线程读取数组?
所以如果一个系统具有很高的并发性,而且大多数线程的操作都是不读写的,最好使用CopyOnWriteArrayList
。
正如此链接所述 :
CopyOnWriteArrayList是在Java 5 Concurrency API中引入的一个并发Collection类,以及Java中stream行的表兄弟ConcurrentHashMap。
CopyOnWriteArrayList实现了List接口,如ArrayList,Vector和LinkedList,但它是一个线程安全的集合,它以与Vector或其他线程安全集合类稍微不同的方式实现其线程安全性。
如名称所示CopyOnWriteArrayList创build基础ArrayList的副本与每个变异操作,例如添加或设置。 通常CopyOnWriteArrayList是非常昂贵的,因为它涉及每个写入操作的昂贵的数组拷贝,但是如果你有一个列表,其中迭代数量超过了变化,那么它非常有效,例如,你大多需要迭代ArrayList,而不是太频繁地修改它。
CopyOnWriteArrayList的迭代器是故障安全的,即使底层CopyOnWriteArrayList被修改一次迭代开始,也不抛出ConcurrentModificationException,因为迭代器在ArrayList的单独副本上运行。 因此,CopyOnWriteArrayList所做的所有更新都不可用于Iterator。
要获得最新版本,请执行一个新的读取,如list.iterator();
话虽如此,更新这个集合很多将会杀死性能。 如果您尝试对CopyOnWriteArrayList进行sorting,您将看到该列表将引发一个UsupportedOperationExceptionexception(对集合进行sorting调用N次)。 您只应在读取90 +%以上时使用此读取。
应对新arrays的目的是什么?
复制底层数组可以保证数据结构的任何迭代都是安全的,因为迭代发生在数据本质上不可变的“快照”上。
是否为其他线程读取数组?
有点。 更具体地说,每个线程都能够安全地迭代数组,而不用担心ConcurrentModificationException
或其他未知/未定义的行为。
因此,如果一个系统的并发性很高,并且大多数线程的操作正在读取而不是写入,那么最好使用CopyOnWriteArrayList。 我对吗?
不,只有在线程的大部分操作都在迭代列表中。 如果大多数活动是基于随机访问的读取,则ReadWriteLock
可能会更好。
从CopyOnWriteArrayList
的javadoc
这通常成本太高,但是当遍历操作的数量远远超过突变时,可能会比替代方法更有效,而且当您不能或不想同步遍历时,它是有用的,但是需要排除并发线程之间的干扰。