原文: https://howtodoinjava.com/java/collections/java-copyonwritearraylist/

Java CopyOnWriteArrayListArrayList线程安全变体,其中的所有可变操作(添加,设置等)均通过对基础数组进行全新复制来实现。

它的不可变快照式迭代器方法在创建迭代器时使用了对数组状态的引用。 这在遍历操作远远超过列表更新操作且我们不想同步遍历并且在更新列表时仍希望线程安全的用例中很有用。

  1. Table of Contents
  2. 1\. CopyOnWriteArrayList Hierarchy
  3. 2\. CopyOnWriteArrayList Features
  4. 3\. CopyOnWriteArrayList Example
  5. 4\. CopyOnWriteArrayList Constructors
  6. 5\. CopyOnWriteArrayList Methods
  7. 6\. CopyOnWriteArrayList Usecases
  8. 7\. CopyOnWriteArrayList Performance
  9. 8\. Conclusion

1. CopyOnWriteArrayList层次结构

CopyOnWriteArrayList类实现以下接口 – ListRandomAccessCloneableserializable

  1. public class CopyOnWriteArrayList<E>
  2. implements List<E>,
  3. RandomAccess,
  4. Cloneable,
  5. Serializable
  6. {
  7. private transient volatile Object[] array;
  8. //implementation
  9. }

2. CopyOnWriteArrayList特性

有关 Java CopyOnWriteArrayList类的重要知识是:

  • CopyOnWriteArrayList类实现ListRandomAccess接口,因此提供ArrayList类中可用的所有特性。
  • 使用CopyOnWriteArrayList进行更新操作的成本很高,因为每个突变都会创建基础数组的克隆副本,并为其添加/更新元素。
  • 它是ArrayList的线程安全版本。 每个访问列表的线程在初始化此列表的迭代器时都会看到自己创建的后备数组快照版本。
  • 因为它在创建迭代器时获取基础数组的快照,所以它不会抛出ConcurrentModificationException
  • 不支持对迭代器的删除操作(删除,设置和添加)。 这些方法抛出UnsupportedOperationException
  • CopyOnWriteArrayList同步列表的并发替代,当迭代次数超过突变次数时,它提供了更好的并发性。
  • 它允许重复的元素和异构对象(使用泛型来获取编译时错误)。
  • 因为它每次创建迭代器时都会创建一个数组的新副本,所以性能比ArrayList

3. CopyOnWriteArrayList示例

显示在不同时间创建的迭代器如何查看CopyOnWriteArrayListlist的快照版本的 Java 程序。 在给定的示例中,当列表具有元素(1,2,3)时,我们首先创建了listitr1

然后,我们在列表中添加了另一个元素,并再次创建了一个迭代器itr2

最后,我们验证了两个迭代器中的元素。

  1. CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>(new Integer[] {1,2,3});
  2. System.out.println(list); //[1, 2, 3]
  3. //Get iterator 1
  4. Iterator<Integer> itr1 = list.iterator();
  5. //Add one element and verify list is updated
  6. list.add(4);
  7. System.out.println(list); //[1, 2, 3, 4]
  8. //Get iterator 2
  9. Iterator<Integer> itr2 = list.iterator();
  10. System.out.println("====Verify Iterator 1 content====");
  11. itr1.forEachRemaining(System.out :: println); //1,2,3
  12. System.out.println("====Verify Iterator 2 content====");
  13. itr2.forEachRemaining(System.out :: println); //1,2,3,4

程序输出。

[1, 2, 3]
[1, 2, 3, 4]
====Verify Iterator 1 content====
1
2
3
====Verify Iterator 2 content====
1
2
3
4

4. CopyOnWriteArrayList构造器

  • CopyOnWriteArrayList():创建一个空列表。
  • CopyOnWriteArrayList(Collection c):创建一个列表,其中包含指定集合的元素,并按集合的迭代器返回的顺序排列。
  • CopyOnWriteArrayList(object[] array):创建一个保存给定数组副本的列表。

5. CopyOnWriteArrayList方法

CopyOnWriteArrayList类支持ArrayList类支持的所有方法。 该行为仅在迭代器(快照迭代器)和列表中发生突变时创建的新支持数组的情况下有所不同。

此外,它提供了一些此类之外的方法。

  • boolean addIfAbsent(Object o):如果不存在,则追加元素。
  • int addAllAbsent(Collection c):按指定集合的迭代器返回的顺序,将指定集合中尚未包含在此列表中的所有元素追加到此列表的末尾 。

对于所有受支持的其他方法,请访问ArrayList方法部分。

6. Java CopyOnWriteArrayList用例

在以下情况下,我们更喜欢使用CopyOnWriteArrayList而不是常规ArrayList

  1. 当在并发环境中使用列表时。
  2. 迭代次数超过了变异操作的次数。
  3. 迭代器在创建时必须具有列表的快照版本。
  4. 我们不想以编程方式同步线程访问

7. Java CopyOnWriteArrayList性能

由于每次更新列表时都要增加创建新支持数组的步骤,因此其性能比ArrayList差。
读取操作没有性能开销,并且两个类执行相同的操作。

8. 总结

在此 Java 集合教程中,我们学习了使用CopyOnWriteArrayList类,它的构造器,方法和用例。 我们学习了CopyOnWriteArrayList内部在 Java 中的工作原理以及CopyOnWriteArrayList与同步ArrayList的工作原理。

我们通过 Java CopyOnWriteArrayList示例程序演示了快照迭代器的工作方式。

在评论中把您的问题交给我。

学习愉快!

参考:

CopyOnWriteArrayList Java 文档