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

总结

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

目录
相关文章
|
测试技术 领域建模 定位技术
基于事件风暴的需求分析 | 方法案例一
事件风暴(Event Storming)源自领域驱动设计社区,由 Alberto Brandolini 在2012 年发明[1]。 事件风暴最早的名字是基于事件的建模(Event-Based Modeling),正如这个名字所暗示的,事件风暴在发明之初的核心目的是领域建模,在今天的大多数文献和实践中,事件风暴的核心关注点都是领域模型和软件架构。
4412 2
基于事件风暴的需求分析 | 方法案例一
|
缓存 监控 小程序
App性能测试揭秘(Android篇)
性能测试在移动测试领域一直是一个大难题,它最直观的表现是用户在前台使用 App 时的主观体验,然而决定体验优劣的背后,涉及到了许许多多的技术变迁。阅读此文,带你揭秘App性能测试。
5353 0
App性能测试揭秘(Android篇)
|
运维 持续交付 网络安全
|
NoSQL 算法 JavaScript
Redis 实现限流的三种方式
Redis 实现限流的三种方式
|
2月前
|
数据采集 搜索推荐 API
淘宝商品评论API接口全解析:从数据采集到情感分析
淘宝商品评论API是淘宝开放平台提供的数据服务,支持开发者获取商品的用户评论、评分、时间、多媒体信息等。接口具备筛选、分页和排序功能,适用于产品优化与市场分析。文章还附有Python调用示例,演示如何请求和解析评论数据。
|
JSON fastjson 数据格式
使用FastJson对json格式字符串、json对象以及javabean直接的相互转换
一、fastJson对于json格式字符串的解析主要用到了一下三个类: JSON:fastJson的解析器,用于JSON格式字符串与JSON对象及javaBean之间的转换。
3924 0
|
11月前
|
JavaScript 开发工具 git
已安装nodejs但是安装hexo报错
已安装nodejs但是安装hexo报错
204 2
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
706 6
|
算法 Java 大数据
利用Java实现随机采样
利用Java实现随机采样
453 0
|
存储 消息中间件 设计模式
新一代消息中间件—Apache Pulsar
新一代消息中间件—Apache Pulsar
1219 102