在什么情况下CopyOnWriteArrayList适合?

时间:2013-07-25 08:42:56

标签: java collections

我正在学习CopyOnWriteArrayList课程。

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

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

2 个答案:

答案 0 :(得分:86)

正如link所述:

CopyOnWriteArrayList是Java 5 Concurrency API中引入的并发Collection类及其在Java中的流行表兄ConcurrentHashMap

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

  

顾名思义,CopyOnWriteArrayList创建底层副本   具有每个突变操作的ArrayList,例如添加或设置。一般   CopyOnWriteArrayList非常昂贵,因为它涉及昂贵   每次写入操作的数组副本,但如果你非常有效   有一个列表,其中迭代次数超过突变,例如你最需要的   迭代ArrayList并且不要经常修改它。

     

CopyOnWriteArrayList的迭代器是故障安全的,不会抛出   ConcurrentModificationException 即使是底层的   迭代开始后,CopyOnWriteArrayList被修改,因为   Iterator在ArrayList的单独副本上运行。因此全部   在迭代器上无法使用对CopyOnWriteArrayList进行的更新。

要获得最新版本,请执行list.iterator();

之类的新阅读

话虽如此,更新此系列将会扼杀性能。如果您尝试对CopyOnWriteArrayList进行排序,则会看到列表抛出UnsupportedOperationException(对集合调用的排序调用次数为N次)。只有在读取90%以上的读数时才应该使用此读数。

答案 1 :(得分:23)

  

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

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

  

其他线程是否可以读取数组?

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

  

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

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

来自CopyOnWriteArrayList

的javadoc
  

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