[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
目录
一. 多线程下使用ArrayList
1.1. 自行判断加锁
1.2 使用Collections.synchronizedList()套壳加锁
1.3 CopyOnWriteArrayList类
二. 总结
一. 多线程下使用ArrayList
多线程下使用ArrayList会涉及到线程安全问题, 例如:
public static void main(String[] args) throws InterruptedException{List<Integer> list = new ArrayList<>();Runnable runnable = () -> {for (int i = 0; i < 50000; i++) {list.add(i);}};// 创建两个线程for (int i = 0; i < 2; i++) {new Thread(runnable).start();}Thread.sleep(5000);System.out.println(list.size());}
可以发现, 最后的结果并不是期待的100000, 这是因为ArrayList中的add方法并没有处理线程安全问题.
那么, 如何解决在多线程场景下使用ArrayList产生的线程安全问题呢? 如下, 有三种解决方案.
1.1. 自行判断加锁
就是根据需要来进行加锁, 将一些可能会产生线程安全问题的操作通过加锁打包成为原子操作.
Runnable runnable = () -> {for (int i = 0; i < 50000; i++) {synchronized (locker) {list.add(i);}}};

结果正如我们所期待的那样.
1.2 使用Collections.synchronizedList()套壳加锁

对读操作和写操作全部都加锁, 保证线程安全. (此时返回的List对象中的重要操作都加锁了)
但是会降低程序运行效率, 因为读操作本身不会产生线程安全问题, 又加锁就是多此一举了!!!
我们来看看synchronizedList类中add方法是怎么实现的,
public void add(int index, E element) {synchronized (mutex) {list.add(index, element);}}

此时, 结果也是正确的.
1.3 CopyOnWriteArrayList类
CopyOnWrite 写时拷贝, 实现了读与读不互斥, 读与写不互斥, 写与写互斥. 保证了线程安全.
那么, 是怎么实现读与写不互斥的呢?
在面临写操作的时候, 会依照旧数组复制一个新数组, 修改操作就在新数组上进行, 最后再将旧数组覆盖.如果在写操作的时候发生了线程切换, 并且切换到了读操作, 此时还是会读取旧数组. 保证了线程安全.
CopyOnWriteArrayList类中add方法的实现:
/*** Appends the specified element to the end of this list.** @param e element to be appended to this list* @return {@code true} (as specified by {@link Collection#add})*/public boolean add(E e) {synchronized (lock) {Object[] es = getArray();int len = es.length;es = Arrays.copyOf(es, len + 1);es[len] = e;setArray(es);return true;}}

结果也是正确的.
二. 总结
1. 多线程下使用ArrayList类, 涉及到了线程安全问题, 以及解决线程安全问题的方法.
2. 自行判断加锁. 效率高
3. Collections.synchronizedList()套壳封装, 效率低下. 因为对不涉及线程安全问题的操作进行加锁.(即对List接口中的所有方法进行加锁)
4. CopyOnWriteArrayList类, 写时拷贝. 实现了读与读, 读与写操作不互斥, 写与写操作互斥. 保证了线程安全, 并且效率相对高效.
相关文章:
[JAVAEE] 面试题(四) - 多线程下使用ArrayList涉及到的线程安全问题及解决
目录 一. 多线程下使用ArrayList 1.1. 自行判断加锁 1.2 使用Collections.synchronizedList()套壳加锁 1.3 CopyOnWriteArrayList类 二. 总结 一. 多线程下使用ArrayList 多线程下使用ArrayList会涉及到线程安全问题, 例如: public static void main(String[] args) thro…...
Elasticsearch-linux环境部署
本文主要介绍linux下elasticsearch的部署。通过在一台linux服务器中分别对elasticsearch-6.7.2版本,elasticsearch-7.3.0版本来进行安装,记录在安装elasticsearch-7.3.0版本时出现的异常情况,以及elasticsearch-head的安装。 基础环境 本机已…...
LeetCode 每日一题 长度为 K 的子数组的能量值
长度为 K 的子数组的能量值 给你一个长度为 n 的整数数组 nums 和一个正整数 k 。 一个数组的 能量值 定义为: 如果 所有 元素都是依次 连续 且 上升 的,那么能量值为 最大 的元素。 否则为 -1 。 你需要求出 nums 中所有长度为 k 的 子数组 的能量值。 …...
人工智能——小白学习指南
知孤云出岫 目录 1. **智能评测系统**2. **个性化学习路径推荐**3. **虚拟学习助手**4. **学习行为分析**5. **数据驱动的教学决策**6. **自动化课程推荐**7. **数据隐私与安全保护** 人工智能知识点的总结和学习路线,以数据表格形式呈现,并附带在教育行…...
go 集成Gin Web开发框架
引入gin的依赖 下载并安装 gin go get -u github.com/gin-gonic/gin 将 gin 引入到代码中 import "github.com/gin-gonic/gin" 开始 package mainimport "github.com/gin-gonic/gin"func main() {r : gin.Default()r.GET("/ping", func(c …...
c++ 多态性
类的多态 多态概念入门 #include <iostream> using namespace std;/* 多态的前提: 拥有继承关系的类中有相同的函数(返回类型、函数名、形参列表) 多态解决的问题:1、派生类的对象被赋值给基类对象时2、派生类的对象初始化基类的引用时3、基类的指针指向派生…...
块存储、文件存储和对象存储详细介绍
块存储、文件存储和对象存储介绍 块存储:像跑车,因为它们都能提供快速的响应和高性能,适合需要即时数据访问的场景,比如数据库和虚拟化技术。 文件存储:像货车,因为它们都能承载大量货物(文件&…...
移植 AWTK 到 纯血鸿蒙 (HarmonyOS NEXT) 系统 (9) - 编译现有的AWTK应用程序
AWTK 应用程序开发完成后,在配置文件中添加 harmonyos 的选项,通过create_project.py脚本即可生成 DevEco Studio的工程。 安装开发环境 DevEco Studio HarmonyOS 的开发工具。 Python 运行环境。 git 源码管理工具。 下载 awtk 和 awtk-harmonyos…...
ssm基于BS的仓库在线管理系统的设计与实现+vue
系统包含:源码论文 所用技术:SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习,获取源码看文章最下面 需要定制看文章最下面 目 录 第一章 绪论 1 1.1 研究背景 1 1.2 研究意义 1 1.3 研究内容 2 第二章 开发环境与技术3 …...
面试题:Spring(一)
1. Spring框架中bean是单例么? Service Scope("singleton") public class UserServiceImpl implements UserService { }singleton : bean在每个Spring IOC容器中只有一个实例。prototype:一个bean的定义可以有多个实例。 2. Spring框架中的…...
MySQ怎么使用语法介绍(详细)
一、什么是库结构 库结构的意思就是指数据库的结构。所以,理解“库结构”就要先理解“库”是什么。 在数据库的上下文中,库指的是一个数据库。简单来说,数据库(库)是用来存储和管理数据的容器。它不仅存储实际的数据…...
新能源汽车与公共充电桩布局
近年来,全球范围内对新能源汽车产业的推动力度不断增强,中国新能源汽车市场也呈现蓬勃发展的势头,在政策与市场的共同推动下,新能源汽车销量持续增长。然而,据中国充电联盟数据显示,充电基础设施建设滞后于新能源汽车数量增长的现状导致充电桩供需不平衡,公共充电桩服务空白区域…...
【GIT】sourceTree的“当前分支“,“合并分支“与“检出分支的区别
GIT三款经典可视化 由上文文档得出灵感写出此篇 这三个概念在 Git 操作中都是很常见的, 来逐个解析: 1. 当前分支 “当前分支”就是你目前正在工作的分支。你在进行任何代码修改、提交等操作时,都会应用到“当前分支”上。换句话说…...
【Git】如何在 Git 中高效合并分支:完整指南
目录 引言1. 切换到主分支1.1 切换分支命令1.2 相关命令1.3 切换分支示意图 2. 合并分支2.1 基本合并命令2.2 合并选项2.3 合并流程示意图 3. 解决冲突3.1 解决冲突的步骤3.2 相关命令3.3 解决冲突示意图 4. 本地更新分支4.1 拉取远程更改4.2 更新主分支4.3 拉取远程更新到本地…...
成都睿明智科技有限公司抖音电商服务效果如何?
在这个短视频风起云涌的时代,抖音电商以其独特的魅力,成为了众多商家竞相追逐的新蓝海。而在这片波澜壮阔的商海中,成都睿明智科技有限公司犹如一艘稳健的航船,引领着无数企业驶向成功的彼岸。今天,就让我们一起揭开成…...
收集的linux命令/Docker命令/git命令
查看linux发行版本 lsb_release -a显示操作系统的发行版号 uname -r1. 启动 Docker。 sudo systemctl start docker2. 通过运行映像来验证 Docker 引擎安装是否成功。hello-world sudo docker run hello-world查看docker版本 docker -v查看docker配置信息 docker infodoc…...
DNS域名解析实验
准备工作 [rootlocalhost ~]# setenforce 0 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# mount /dev/sr0 /mnt [rootlocalhost ~]# dnf install bind -y DNS正向解析: 对主配置文件进行修改 [rootlocalhost ~]# vim /etc/named.conf 正向解析…...
Dify 本地部署指南
一、前置条件 Clone Dify 代码: git clone https://github.com/langgenius/dify.git 在启用业务服务之前,我们需要先部署 PostgresSQL / Redis / Weaviate(如果本地没有的话),可以通过以下命令启动: cd…...
15分钟学 Go 第 38 天:数据库基础
第38天 - 数据库基础 学习目标 学习如何连接和操作数据库,包括基本的增、删、改、查功能,以及如何使用Go语言中的database/sql包进行数据库交互。 内容概述 在现代应用程序中,数据库是数据持久化的重要部分。Go语言通过database/sql包提供…...
【Python】图片处理
一、获取图片尺寸 优点缺点Pillow功能丰富,支持多种图像处理操作。使用简单,适合快速原型开发。对于处理大型图像或批量图像时,性能可能不如OpenCV。OpenCV性能强大,适合处理大型图像和视频处理。提供了丰富的计算机视觉算法。相…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...
aardio 自动识别验证码输入
技术尝试 上周在发学习日志时有网友提议“在网页上识别验证码”,于是尝试整合图像识别与网页自动化技术,完成了这套模拟登录流程。核心思路是:截图验证码→OCR识别→自动填充表单→提交并验证结果。 代码在这里 import soImage; import we…...
【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理:检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目:RankRAG:Unifying Context Ranking…...
如何把工业通信协议转换成http websocket
1.现状 工业通信协议多数工作在边缘设备上,比如:PLC、IOT盒子等。上层业务系统需要根据不同的工业协议做对应开发,当设备上用的是modbus从站时,采集设备数据需要开发modbus主站;当设备上用的是西门子PN协议时…...


