【问题标题】:In what situations is the CopyOnWriteArrayList suitable? [duplicate]CopyOnWriteArrayList 适用于什么情况? [复制]
【发布时间】:2013-07-25 08:42:55
【问题描述】:

我正在学习CopyOnWriteArrayList 课程。

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

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

【问题讨论】:

    标签: java collections


    【解决方案1】:

    正如link 所述:

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

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

    顾名思义,CopyOnWriteArrayList 创建底层副本 ArrayList 与每个突变操作,例如添加或设置。一般 CopyOnWriteArrayList 非常昂贵,因为它涉及成本高昂 每次写入操作时都进行数组复制,但 如果您这样做会非常有效 有一个迭代超过突变的列表,例如你主要需要 迭代 ArrayList,不要经常修改。

    CopyOnWriteArrayList 的迭代器是故障安全的,不会抛出异常 ConcurrentModificationException 即使底层 一旦迭代开始,CopyOnWriteArrayList 就会被修改,因为 迭代器在 ArrayList 的单独副本上运行。因此所有 在 CopyOnWriteArrayList 上所做的更新不适用于 Iterator。

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

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

    【讨论】:

    • 如果您需要非常频繁地将项目添加到列表中,有时需要全部删除。您认为“同步”方式更好吗?
    • 您可以考虑java.util.concurrent 包而不是Collections.synchronizedList
    • 我已经在使用它了。但它似乎只在我与旧的 synchronized 关键字结合使用时才起作用。
    • 刚读到这里,现在我明白了。当您迭代 Set 时,我们不需要使用 synchronized 关键字,即使我们使用 Collections.synchronizedList
    • @stdout - 不,它不会抛出 ConcurrentModificationException 。这是一个故障安全集合,它使用单独的副本进行迭代。
    【解决方案2】:

    应对新数组的目的是什么?

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

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

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

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

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

    来自CopyOnWriteArrayList的javadoc

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

    【讨论】:

    • 您能解释一下为什么ReadWriteLock 可能会更好吗?
    • 因为CopyOnWriteArrayList 用于安全遍历。使用它的代价是为每次修改复制底层引用数组,并可能为迭代结构的陈旧版本的线程保留多个副本。 ReadWriteLock 将允许多个读者,并且仍然允许偶尔的作者执行必要的修改。
    猜你喜欢
    • 1970-01-01
    • 2017-03-05
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    • 2012-07-10
    • 2015-10-26
    • 2019-03-10
    相关资源
    最近更新 更多