当前位置: 首页 > news >正文

【JUC】三、集合的线程安全

文章目录

  • 1、ArrayList集合线程安全问题分析
  • 2、解决方式一:Vector或synchronizedList( )
  • 3、解决方式二:CopyOnWriteArrayList 写时复制
  • 4、HashSet集合线程不安全的分析与解决
  • 5、HashMap集合线程不安全的分析与解决

1、ArrayList集合线程安全问题分析

对List集合非线程安全的Demo代码:

public class ArrayListDemo {public static void main(String[] args) {List<String> list = new ArrayList<>();//多个线程同时写入List集合for (int i = 0; i < 10; i++) {new Thread(() -> {//加元素list.add(UUID.randomUUID().toString().substring(0,8));//遍历输出集合System.out.println(list);},String.valueOf(i)).start();}}
}

运行:

在这里插入图片描述

ConcurrentModificationException异常,是在多线程环境下,当一个线程正在遍历集合,而另一个线程对集合进行了修改操作时,就会抛出这个异常。以ArrayList为例,其add方法源码,未加synchronized关键字:

在这里插入图片描述

再点击报错详情,进入抛出异常的方法:

在这里插入图片描述

modCount即集合新增的次数,是实际修改次数,而expectedModCount是预期修改次数,它是ArrayList的一个内部类Itr的成员变量,调用iterator()获取迭代器时,内部创建Itr对象,此时,modCount会赋值给expectedModCount:

在这里插入图片描述

拿到迭代器对象,要遍历集合时,modCount已经赋值给expectedModCount,而此时其他线程继续add,modCount+1,modCount和expectedModCount就不相等了。

2、解决方式一:Vector或synchronizedList( )

List接口的另一个实现类Vector,其add方法加了关键字,使用它可解决线程安全问题,但很古老了,since1.2,很少用了。

在这里插入图片描述

List<String> list = new Vector<>();
//重复代码略

同样一种古老的解决方案,可以用Collections的synchronizedList方法,传入一个有线程安全问题的List,如ArrayList:

List<String> list = Collections.synchronizedList(new ArrayList<>());

3、解决方式二:CopyOnWriteArrayList 写时复制

List<String> list = new CopyOnWriteArrayList<>();

完整demo:

public class ArrayListDemo {public static void main(String[] args) {List<String> list = new CopyOnWriteArrayList<>();//多个线程同时写入List集合for (int i = 0; i < 10; i++) {new Thread(() -> {//加元素list.add(UUID.randomUUID().toString().substring(0,8));//遍历输出集合System.out.println(list);},String.valueOf(i)).start();}}
}

原理是写时复制技术,即:

  • 对这个List实现类的集合,可以多线程并发读
  • 往集合中写的时候,则只能独立写,先复制一份原来的集合,这个时候读还是读原来的,然后往新集合里面写入新的内容
  • 写完后新旧合并,再读时,就读这个合并后的集合

在这里插入图片描述
看下源码,再对照着理解写时复制:

在这里插入图片描述

4、HashSet集合线程不安全的分析与解决

public class HashSetDemo {public static void main(String[] args) {Set<String> set = new HashSet<>();for (int i = 0; i < 30; i++) {new Thread(() -> {//写入set.add(UUID.randomUUID().toString().substring(0,8));//读System.out.println(set);},String.valueOf(i)).start();}}
}

运行:

在这里插入图片描述

解决办法类比上面的List,使用CopyOnWriteArraySet

Set<String> set = new CopyOnWriteArraySet<>();

5、HashMap集合线程不安全的分析与解决

public class HashSetDemo {public static void main(String[] args) {Map<String,string> map = new HashMap<>();for (int i = 0; i < 30; i++) {String key = String.valueOf(i);new Thread(() -> {//写入map.put(key,UUID.randomUUID().toString().substring(0,8));//读System.out.println(map);},String.valueOf(i)).start();}}
}

在这里插入图片描述
解决办法类比List,用ConcurrentHashMap

Map<String,String> map = new ConcurrentHashMap<>();

相关文章:

【JUC】三、集合的线程安全

文章目录 1、ArrayList集合线程安全问题分析2、解决方式一&#xff1a;Vector或synchronizedList( )3、解决方式二&#xff1a;CopyOnWriteArrayList 写时复制4、HashSet集合线程不安全的分析与解决5、HashMap集合线程不安全的分析与解决 1、ArrayList集合线程安全问题分析 对…...

使用 Redis 实现生成分布式全局唯一ID(使用SpringBoot环境实现)

目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1、使用 Redis 计数器实现2.2、使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1、编写获取工具3.2、测试获取工具 四、总结 一、前言 在很多项目中生成类似订单编号、用户编号等有唯一性数…...

Pytorch CUDA CPP简易教程,在Windows上操作

文章目录 前言一、使用的工具二、学习资源分享三、libtorch环境配置1.配置CUDA、nvcc、cudnn2.下载libtorch3.CLion配置libtorch4.CMake Application指定Environment variables5.测试libtorch 四、PyTorch CUDA CPP项目流程1.使用CLion结合torch extension编写可以调用cuda的C代…...

服务器怎么连接

服务器怎么连接 服务器可以通过多种方式连接&#xff0c;主要取决于服务器的操作系统、网络配置和连接方式等因素。 1. SSH连接&#xff1a;如果服务器使用的是Linux操作系统&#xff0c;可以通过SSH协议连接。需要使用SSH客户端工具&#xff0c;例如PuTTY&#xff0c;在登录页…...

线性代数-Python-05:矩阵的逆+LU分解

文章目录 1 矩阵的逆1.1 求解矩阵的逆 2 初等矩阵2.1 初等矩阵和可逆性 3 矩阵的LU分解3.1 LU分解的实现 1 矩阵的逆 1.1 求解矩阵的逆 def inv(A):if A.row_num() ! A.col_num():return Nonen A.row_num()"""矩阵A单位矩阵"""ls LinearSyste…...

shell实用脚本命令

1. declare declare 命令是一个非常常用的命令之一&#xff0c;它可以用来声明变量的类型和属性&#xff0c;比如变量的作用域、是否只读等等。 一、declare命令的基本用法 declare 命令可以用来声明变量&#xff0c;其最基本的用法如下&#xff1a;declare 变量名 在上面的命…...

STM32——端口复用与重映射概述与配置(HAL库)

文章目录 前言一、什么是端口复用&#xff1f;什么是重映射&#xff1f;有什么区别&#xff1f;二、端口复用配置 前言 本篇文章介绍了在单片机开发过程中使用的端口复用与重映射。做自我学习的简单总结&#xff0c;不做权威使用&#xff0c;参考资料为正点原子STM32F1系列精英…...

ABZ正交编码 - 异步电机常用的位置信息确定方式

什么是正交编码&#xff1f; ab正交编码器&#xff08;又名双通道增量式编码器&#xff09;&#xff0c;用于将线性移位转换为脉冲信号。通过监控脉冲的数目和两个信号的相对相位&#xff0c;用户可以跟踪旋转位置、旋转方向和速度。另外&#xff0c;第三个通道称为索引信号&am…...

Linux学习第41天:Linux SPI 驱动实验(二):乾坤大挪移

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本章的思维导图如下&#xff1a; 二、I.MX6U SPI主机驱动分析 主机驱动一般都是由SOC厂商写好的。不作为重点需要掌握的内容。 三、SPI设备驱动编写流程 1、SP…...

黑客泄露 3500 万条 LinkedIn 用户记录

被抓取的 LinkedIn 数据库分为两部分泄露&#xff1a;一部分包含 500 万条用户记录&#xff0c;第二部分包含 3500 万条记录。 LinkedIn 数据库保存了超过 3500 万用户的个人信息&#xff0c;被化名 USDoD 的黑客泄露。 该数据库在臭名昭著的网络犯罪和黑客平台 Breach Forum…...

Flink SQL -- 反压

1、测试反压&#xff1a; 1、反压&#xff1a; 指的是下游消费数据的速度比上游产生数据的速度要小时会出现反压&#xff0c;下游导致上游的Task反压。 2、测试反压&#xff1a;使用的是DataGen CREATE TABLE words (word STRING ) WITH (connector datagen,rows-per-second…...

快速入门安装及使用git与svn的区别常用命令

一、导言 1、什么是svn&#xff1f; SVN是Subversion的简称&#xff0c;是一个集中式版本控制系统。与Git不同&#xff0c;SVN没有分布式的特性。在SVN中&#xff0c;项目的代码仓库位于服务器上&#xff0c;团队成员通过向服务器提交和获取代码来实现版本控制。SVN记录了每个…...

超详细介绍如何使用 OpenCV 和 BGS 库进行背景扣除

深入研究这些 CV 系统背后的想法,我们可以观察到,在大多数情况下,初始步骤包含背景减除 (BS),这有助于获得视频流中对象的相对粗略和快速的识别,以便对其进行进一步的精细处理。在当前的文章中,我们将介绍几种在准确性和处理时间 BS 方法方面值得注意的算法:SuBSENSE和基…...

STM32F4、GD32F4 内部硬件CRC使用方法和踩坑实录

背景 某项目用到了IC卡刷卡启动功能,程序中对读取IC卡的相关数据后要进行CRC校验,本文介绍如何在STM32F4 GD32F4 平台上使用标准库函数进行CRC硬件校验。 摘要 本文介绍如何在STM32F4、GD32F4 平台上使用标准库函数进行CRC硬件校验。包括容易出现的问题和解决方法。涉及STM3…...

【SpringBoot】序列化和反序列化介绍

一、认识序列化和反序列化 Serialization&#xff08;序列化&#xff09;是一种将对象以一连串的字节描述的过程&#xff1b;deserialization&#xff08;反序列化&#xff09;是一种将这些字节重建成一个对象的过程。将程序中的对象&#xff0c;放入文件中保存就是序列化&…...

Android 升级软件后清空工厂模式测试进度

Android 升级软件后清空工厂模式测试进度 最近收到项目需求反馈&#xff1a;升级软件后,进入工厂模式测试项,界面显示测试项保留了升级前的测试状态&#xff08;有成功及失败&#xff09;,需修改升级软件后默认清空测试项测试状态&#xff0c;具体修改参照如下&#xff1a; /…...

Promise原理、以及Promise.race、Promise.all、Promise.resolve、Promise.reject实现;

为了向那道光亮奔过去&#xff0c;他敢往深渊里跳&#xff1b; 于是今天朝着Promise的实现前进吧&#xff0c;写了四个小时&#xff0c;终于完结撒花&#xff1b; 我知道大家没有耐心&#xff0c;当然我也坐的腰疼&#xff0c;直接上代码&#xff0c;跟着我的注释一行行看过去…...

mysql---MHA(高可用)

MHA概述 magterhight availabulity :基于主库的高可用环境下&#xff0c;主故障切换基础要求&#xff1a;主从架构 &#xff08;一主两从&#xff09;解决mysql的单点故障问题&#xff0c;一旦数据库崩溃&#xff0c;MHA会在0-30s内这东东完成故障切换。复制方式&#xff1a;半…...

人工智能基础_机器学习032_多项式回归升维_原理理解---人工智能工作笔记0072

现在开始我们来看多项式回归,首先理解多维 原来我们学习的使用线性回归,其实就是一条直线对吧,那个是一维的,我们之前学的全部都是一维的对吧,是一维的,然后是多远的,因为有多个x1,x2,x3,x4... 但是比如我们有一个数据集,是上面这种,的如果用一条直线很难拟合,那么 这个时候,…...

C#截取范围

string[] strs new string[]{"1e2qe","23123e21","3ewqewq","4fewfew","5fsdfds"};var list strs[1..2];Range p 0..3;var list strs[Range];...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

Springboot社区养老保险系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;社区养老保险系统小程序被用户普遍使用&#xff0c;为方…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

Spring Security 认证流程——补充

一、认证流程概述 Spring Security 的认证流程基于 过滤器链&#xff08;Filter Chain&#xff09;&#xff0c;核心组件包括 UsernamePasswordAuthenticationFilter、AuthenticationManager、UserDetailsService 等。整个流程可分为以下步骤&#xff1a; 用户提交登录请求拦…...