Java 中 CopyOnWriteArrayList和CopyOnWriteArraySet

什么是CopyOnWriteArrayList和CopyOnWriteArraySet

CopyOnWriteArrayList和CopyOnWriteArraySet都是Java并发编程中提供的线程安全的集合类。

CopyOnWriteArrayList是一个线程安全的ArrayList,其内部通过volatile数组和显式锁ReentrantLock来实现线程安全。它采用了一种称为“写入时复制”(Copy-On-Write)的策略,即当进行修改操作时,会先复制一份当前数据,然后在新的数据上进行修改,修改完成后再将指向原来数据的引用指向新的数据。这样可以保证读操作可以并发进行而不会被阻塞,同时也保证了数据的线程安全性。

CopyOnWriteArraySet是一个线程安全的Set,其内部实现是基于CopyOnWriteArrayList的。它持有一个CopyOnWriteArrayList的引用,所有的操作都是由这个CopyOnWriteArrayList来实现的。与CopyOnWriteArrayList不同的是,CopyOnWriteArraySet是无序的,并且不允许存放重复值。

由于CopyOnWriteArrayList和CopyOnWriteArraySet的写操作都需要复制底层数组,因此如果集合较大或者写操作非常频繁,那么这种实现方式的性能可能会比较低。因此,在选择使用这些集合类时需要根据具体的应用场景进行权衡。

另外,需要注意的是,虽然CopyOnWriteArrayList和CopyOnWriteArraySet的读操作可以在不加锁的情况下进行,但是并不是所有的读操作都是完全无锁的。例如,迭代器在迭代过程中会持有底层数组的引用,如果在这个过程中发生了写操作,那么迭代器可能会抛出ConcurrentModificationException异常。因此,在使用迭代器进行遍历时需要特别注意。

代码示例

下面是使用CopyOnWriteArrayList和CopyOnWriteArraySet的简单代码示例:

CopyOnWriteArrayList示例

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;public class CopyOnWriteArrayListExample {public static void main(String[] args) {// 创建一个CopyOnWriteArrayListList<String> list = new CopyOnWriteArrayList<>();// 添加元素list.add("Element 1");list.add("Element 2");list.add("Element 3");// 在新的线程中修改列表new Thread(() -> {list.add("Element 4"); // 线程安全地添加元素}).start();// 主线程中迭代列表for (String element : list) {System.out.println(element); // 读取操作也是线程安全的}}
}

CopyOnWriteArraySet示例

import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;public class CopyOnWriteArraySetExample {public static void main(String[] args) {// 创建一个CopyOnWriteArraySetSet<String> set = new CopyOnWriteArraySet<>();// 添加元素set.add("Element 1");set.add("Element 2");set.add("Element 3");// 在新的线程中修改集合new Thread(() -> {set.add("Element 4"); // 线程安全地添加元素}).start();// 主线程中迭代集合for (String element : set) {System.out.println(element); // 读取操作也是线程安全的}}
}

在上面的两个示例中,CopyOnWriteArrayList和CopyOnWriteArraySet都是在多线程环境中安全使用的。即使在修改集合(添加元素)的同时,其他线程也可以安全地迭代集合。这是因为写操作(如添加元素)会创建一个集合的新副本,并在修改完成后替换旧副本。这样,读取操作可以安全地继续进行,而不会受到写操作的干扰。

需要注意的是,由于写操作需要复制整个底层数组,因此如果集合非常大,或者写操作非常频繁,性能可能会受到影响。在这种情况下,可能需要考虑使用其他并发集合,如ConcurrentHashMap的keySet或entrySet视图,或者自定义的并发解决方案。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/696996.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决ios17无法复制的问题

原代码写过一片js实现复制的代码 那段代码有问题 以下是之前写的一段有问题的原代码&#xff1a; let url "kkkkkk";const hiddenTextarea document.createElement("textarea");hiddenTextarea.style.position "absolute";hiddenTextarea.st…

ArcgisForJS如何实现添加含图片样式的点要素?

文章目录 0.引言1.加载底图2.获取点要素的坐标3.添加含图片样式的几何要素4.完整实现 0.引言 ArcGIS API for JavaScript 是一个用于在Web和移动应用程序中创建交互式地图和地理空间分析应用的库。本文在ArcGIS For JavaScript中使用Graphic对象来创建包含图片样式的点要素。 …

MIT-6.824-Lab2,Raft部分笔记|Use Go

文章目录 前记Paper6&#xff1a;RaftLEC5、6&#xff1a;RaftLAB22AtaskHintlockingstructureguide设计与编码 2BtaskHint设计与编码 2CtaskHint question后记 LEC5&#xff1a;GO, Threads, and Raftgo threads技巧raft实验易错点debug技巧 前记 趁着研一考完期末有点点空余…

软考29-上午题-【数据结构】-排序

一、排序的基本概念 1-1、稳定性 稳定性指的是相同的数据所在的位置经过排序后是否发生变化。若是排序后&#xff0c;次序不变&#xff0c;则是稳定的。 1-2、归位 每一趟排序能确定一个元素的最终位置。 1-3、内部排序 排序记录全部存放在内存中进行排序的过程。 1-4、外部…

vue使用.sync和update实现父组件与子组件数据绑定的案例

在 Vue 中&#xff0c;.sync 是一个用于实现双向数据绑定的特殊修饰符。它允许父组件通过一种简洁的方式向子组件传递一个 prop&#xff0c;并在子组件中修改这个 prop 的值&#xff0c;然后将修改后的值反馈回父组件&#xff0c;实现双向数据绑定。 使用 .sync 修饰符的基本语…

微信小程序 --- wx.request网络请求封装

网络请求封装 网络请求模块难度较大&#xff0c;如果学习起来感觉吃力&#xff0c;可以直接学习 [请求封装-使用 npm 包发送请求] 以后的模块 01. 为什么要封装 wx.request 小程序大多数 API 都是异步 API&#xff0c;如 wx.request()&#xff0c;wx.login() 等。这类 API 接口…

【精选】Java面向对象进阶——内部类

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

【操作系统】磁盘文件管理系统

实验六 磁盘文件管理的模拟实现 实验目的 文件系统是操作系统中用来存储和管理信息的机构&#xff0c;具有按名存取的功能&#xff0c;不仅能方便用户对信息的使用&#xff0c;也有效提高了信息的安全性。本实验模拟文件系统的目录结构&#xff0c;并在此基础上实现文件的各种…

FISCO BCOS(十七)利用脚本进行区块链系统监控

要利用脚本进行区块链系统监控&#xff0c;你可以使用各种编程语言编写脚本&#xff0c;如Python、Shell等 利用脚本进行区块链系统监控可以提高系统的稳定性、可靠性&#xff0c;并帮助及时发现和解决潜在问题&#xff0c;从而确保区块链网络的正常运行。本文可以利用脚本来解…

Java实战:分布式Session解决方案

本文将详细介绍Java分布式Session的解决方案。我们将探讨分布式Session的基本概念&#xff0c;以及常见的分布式Session管理技术&#xff0c;如Cookie、Token、Redis等。此外&#xff0c;我们将通过具体的示例来展示如何在Java应用程序中实现分布式Session。本文适合希望了解和…

Swift基础知识:21.Swift继承

在 Swift 中&#xff0c;类可以通过继承从其他类获得属性和方法。被继承的类称为父类&#xff08;或超类&#xff09;&#xff0c;继承的类称为子类。子类可以继承父类的特性&#xff0c;并且可以添加自己的新特性。继承允许类层次结构中的代码重用和多态性。 定义一个基类&am…

Vue3 使用动态组件 component

component 标签&#xff1a;用于动态渲染标签或组件。 语法格式&#xff1a; <component is"标签或组件名">标签内容</component> 动态渲染标签&#xff1a; <template><h3>我是父组件</h3><component is"h1">动态…

SpringCloud(15)之SpringCloud Gateway

一、Spring Cloud Gateway介绍 Spring Cloud Gateway 是Spring Cloud团队的一个全新项目&#xff0c;基于Spring 5.0、SpringBoot2.0、 Project Reactor 等技术开发的网关。旨在为微服务架构提供一种简单有效统一的API路由管理方式。 Spring Cloud Gateway 作为SpringCloud生态…

(delphi11最新学习资料) Object Pascal 学习笔记---第5章第3节(自定义托管记录)

5.3.5 运算符和自定义托管记录 ​ 在 Delphi 语言中&#xff0c;有一组特殊的运算符可用于记录&#xff0c;以定义自定义托管记录。在此之前&#xff0c;请允许我回顾一下记录内存初始化的规则&#xff0c;以及普通记录和托管记录之间的区别。 ​ Delphi 中的记录可以包含任何…

大语言模型LangChain本地知识库:向量数据库与文件处理技术的深度整合

文章目录 大语言模型LangChain本地知识库&#xff1a;向量数据库与文件处理技术的深度整合引言向量数据库在LangChain知识库中的应用文件处理技术在知识库中的角色向量数据库与文件处理技术的整合实践挑战与展望结论 大语言模型LangChain本地知识库&#xff1a;向量数据库与文件…

【Unity】MySql +Navicat 安装教程

问题描述 在使用Unity开发的时候&#xff0c;有的时候我们是需要使用Mysql数据库的&#xff0c;本教程使用的MySql 和Navicat均为免安装版 ❶mysql安装 1.下载mysql解压至任意目录&#xff0c;此处以“C:\mysql-5.6.39-winx64”为例. mysql百度云连接&#xff1a; 链接&…

Java的递归【详解】

1.认识递归基础知识 什么是方法递归&#xff1f; 递归是一种算法&#xff0c;在程序设计语言中广泛应用。 从形式上说&#xff1a;方法调用自身的形式称为方法递归&#xff08; recursion&#xff09;。 递归的形式&#xff1a; 直接递归&#xff1a;方法自己调用自己。 间接递…

【监控】Spring Boot+Prometheus+Grafana实现可视化监控

目录 1.概述 2.spring actuator 3.Prometheus 3.1.介绍 3.2.使用 1.client端的配置 2.server端的配置 4.grafana 5.留个尾巴 1.概述 本文是博主JAVA监控技术系列的第四篇&#xff0c;前面已经聊过了JMX、Spring actuator等技术&#xff0c;本文我们就将依托于Spring …

利用docker一键部署LLaMa到自己的Linux服务器,有无GPU都行、可以指定GPU数量、支持界面对话和API调用,离线本地化部署包含模型权重合并

利用docker一键部署LLaMa到自己的Linux服务器,有无GPU都行、可以指定GPU数量、支持界面对话和API调用,离线本地化部署包含模型权重合并。两种方式实现支持界面对话和API调用,一是通过搭建text-generation-webui。二是通过llamma.cpp转换模型为转换为 GGUF 格式,使用 quanti…

Leetcode日记 889. 根据前序和后序遍历构造二叉树

Leetcode日记 889. 根据前序和后序遍历构造二叉树 给定两个整数数组&#xff0c;preorder 和 postorder &#xff0c;其中 preorder 是一个具有 无重复 值的二叉树的前序遍历&#xff0c;postorder 是同一棵树的后序遍历&#xff0c;重构并返回二叉树。 如果存在多个答案&#…