CopyOnWriteArrayList的使用,你了解么?

简介: CopyOnWriteArrayList的使用,你了解么?

前言

Java中的CopyOnWriteArrayList是List接口的线程安全实现。它属于java.util.concurrent包,是ArrayList实现的增强版本。

顾名思义,CopyOnWriteArrayList为每个add()或set()操作创建基于ArrayList的克隆内部副本。由于此额外的开销成本,理想情况下,仅当我们具有非常频繁的读取操作并且没有很多插入或更新时,才应使用CopyOnWriteArrayList。


构建CopyOnWriteArrayList

我们可以使用以下构造函数之一创建一个CopyOnWriteArrayList:

  • CopyOnWriteArrayList():创建一个空列表
  • CopyOnWriteArrayList(Collection c):创建一个使用c中所有元素初始化的列表
  • CopyOnWriteArrayList(Object [] obj):创建一个包含以下内容的列表:给定数组obj的副本让我们看几个示例:

示例代码如下:

CopyOnWriteArrayList<String> emptyList
 = new CopyOnWriteArrayList<>(); //[]
list.add("A");
CopyOnWriteArrayList<String> listUsingCollection =
 new CopyOnWriteArrayList<>(list); //["A"]
CopyOnWriteArrayList<String> listUsingArr =
 new CopyOnWriteArrayList<>(new String[] {"A", "B"}); //["A", "B"]

就像ArrayList一样,它为List接口的所有方法提供实现。


在CopyOnWriteArrayList上进行插入和迭代

众所周知,ArrayList的迭代器是快速失败的,即一旦实例化迭代器,当它在列表中检测到任何修改时,它将抛出ConcurrentModificationException。这也是很多

小伙伴初学者,在开发过程中,经常遇到的异常之一。

CopyOnWriteArrayList具有故障保护迭代器,即使我们在迭代过程中修改列表也不会引发异常。这是因为迭代器正在原始列表的克隆内部副本上进行操作。

但是,稍后实例化的迭代器将看不到对该列表所做的任何修改。

假设我们有一个CopyOnWriteArrayList实例,该实例当前包含两个元素:

CopyOnWriteArrayList<String> list =
 new CopyOnWriteArrayList<>(new String[] {"A", "B"});

现在让我们获得一个Iterator实例,以便能够对其元素进行迭代:

Iterator itr = list.iterator();

创建完Iterator实例后,现在将更多元素添加到列表中:

list.add("C"); //此处将不会抛出上述异常

现在,让我们使用之前创建的itr遍历列表中的元素:

while(itr.hasNext()) {
   System.out.print(itr.next() + " ");
}

打印结果如下所示:

A
B

如我们所讲,它不会反映列表的当前状态,而只会打印“ A”和“ B”作为其元素。

通过CopyOnWriteArrayList进行删除和迭代

CopyOnWriteArrayList的迭代器不支持remove()操作。任何尝试这样做都会导致UnsupportedOperationException,很多同学在使用时,没有注意到此异

常,面试该类,也是常常会被提及的问题。

@Test(expected = UnsupportedOperationException.class)
public void iterationAndRemoval() {
   CopyOnWriteArrayList<String> list
     = new CopyOnWriteArrayList<>(new String[]{"A", "B"});
   Iterator<String> itr = list.iterator();
   while (itr.hasNext()) {
       itr.remove();
  }
}

ArrayList vs CopyOnWriteArrayList

让我们梳理一下Java ArrayList和CopyOnWriteArrayList类之间的区别:

ArrayList CopyOnWriteArrayList
属于java.util包,非线程安全的 是线程安全的实现,并且存在于java.util.concurrent包中
具有快速失败的迭代器,一旦迭代开始,它会在检测到任何修改时引发ConcurrentModificationException 有一个故障安全的迭代器,因为该迭代器保存列表的克隆副本
迭代器支持remove()操作 迭代器不支持remove()操作,抛出UnsupportedOperationException

总结

了解区别与联系,才能更好地使用,基于以上的区别,相信大家对于使用应该会有更明确清晰的认识。

目录
相关文章
|
5月前
|
存储 安全 Java
线程安全集合类
线程安全集合类
33 1
|
5月前
|
安全 Java 容器
线程安全的集合类
线程安全的集合类
|
1月前
|
存储 安全 算法
JUC集合: ConcurrentLinkedQueue详解
与此同时,它的无界特性在使用时需要注意,因为过多的数据累积可能会导致内存消耗过大。合理应用 `ConcurrentLinkedQueue` 不仅可以提升应用性能,还能提高程序在并发环境下的可靠性。在实际的开发过程中,合理选择适当的并发容器对于构建高效稳定的系统至关重要。
31 2
|
2月前
|
安全 Java 容器
CopyOnWriteArrayList原理
文章主要讨论了CopyOnWriteArrayList的工作原理。CopyOnWriteArrayList通过“写时复制”的策略和ReentrantLock锁来保证线程安全性,适用于读多写少的场景;该实现牺牲了一定的写入性能(因为每次写入都需要复制整个数组),但显著提高了读取性能;在多线程环境中,特别是读取操作远多于写入操作时,CopyOnWriteArrayList是一个非常有效的选择。
|
安全
HashMap 是线程安全的吗?
HashMap 是线程安全的吗?
69 0
|
算法 安全
CopyOnWriteArrayList
CopyOnWriteArrayList
|
安全 Java 大数据
CopyOnWriteArrayList 是如何保证线程安全的?
在上一篇文章里,我们聊到了ArrayList 的线程安全问题,其中提到了 CopyOnWriteArrayList 的解决方法。那么 CopyOnWriteArrayList 是如何解决线程安全问题的,背后的设计思想是什么,今天我们就围绕这些问题展开。
99 0
|
存储 安全 Java
Java集合 - ConcurrentHashMap
本篇文章介绍 Java 集合中的 ConcurrentHashMap。 1、CHM 的底层存储结构; 2、CHM 的新增操作的处理逻辑; 3、CHM 的数组扩容机制; 4、CHM 的查询操作的处理逻辑; 5、CHM 的计数;
122 0
|
存储 Java 编译器
|
缓存 安全 Java
看了CopyOnWriteArrayList后自己实现了一个CopyOnWriteHashMap
看了CopyOnWriteArrayList后自己实现了一个CopyOnWriteHashMap
195 0
看了CopyOnWriteArrayList后自己实现了一个CopyOnWriteHashMap