ArrayList线程安全问题解决方案

jdk8 Stream API的出现大大简化了我们对于集合元素的处理代码,对于串行流来说,无需考虑线程安全问题;但是,对于并行流来说,由于它是以多线程的方式并行处理同一个集合中的数据元素的,因此,存在着线程安全问题。

使用并行流向一个集合元素中存入数据,由于集合对象作为共享资源来使用,如果不注意,就会存在线程安全问题。此问题的发现是由于实际生产过程中,集合对象存入数据之前进行了判空操作,不为空才加入数据,但是后续的结果中还是出现了空数据导致的空指针异常。
示例代码:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class Test {public static void main(String[] args) {List<Stu> addStaffPayDocs = new ArrayList<>();for(int x= 0; x< 10000;x++){Stu stu = new Stu();stu.setName(x+"name");stu.setId(x+"id");addStaffPayDocs.add(stu);}List<Stu> docList = new ArrayList<>();addStaffPayDocs.parallelStream().forEach(staffDoc -> {Stu doc = makeDoc(staffDoc);if (doc != null) docList.add(doc);});int count = 0;for(Stu doc : docList){if(null == doc){count++;}}System.out.println("exist null entity "+count );}public static Stu makeDoc(Stu s){Stu stu = new Stu();Random r = new Random();float f = r.nextFloat();stu.setId(f*1000+"id");stu.setName(f*10000+"name"+ s.getName());return stu;}
}class Stu{private String name;private String id;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}
}

代码的期望结果是docList中不会存在空对象,但是实际生产中出现了空对象,排查发现是由于并行流多线程操作线程不安全的ArrayList导致的。
在这里插入图片描述

ArrayList 源码add方法中

public boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;
}

add()方法没有使用同步互斥,所以在多线程并发中,会出现线程异常。

方法1

此时最简单的解决方案就是将docList 改成线程安全的CopyOnWriteArrayList,改完后,测试发现docList不存在空对象。
在这里插入图片描述

List docList = new CopyOnWriteArrayList<>();

写时复制,add()方法中有可重入锁,防止多个线程争抢写,将原件复制一份,修改复制出来的,通过setArray()方法将原件地址指向复制件,所有线程可以读原件,当前线程修改复印件,读写不冲突。通过加锁和写时复制思想可以很好保证了多线程情况下所有线程都可以读,但是只有一个线程在写,因此不会出现并发修改异常。
在这里插入图片描述

方法2

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;public class Test {public static void main(String[] args) {List<Stu> addStaffPayDocs =  new ArrayList<>();for(int x= 0; x< 10000;x++){Stu stu = new Stu();stu.setName(x+"name");stu.setId(x+"id");addStaffPayDocs.add(stu);}List<Stu> docList =  new ArrayList<>();//synchronized objectObject o = new Object();addStaffPayDocs.parallelStream().forEach(staffDoc -> {Stu doc = makeDoc(staffDoc);synchronized (o){if (doc != null) docList.add(doc);}});int count = 0;for(Stu doc : docList){if(null == doc){count++;}}System.out.println("exist null entity "+count );}public static Stu makeDoc(Stu s){Stu stu = new Stu();Random r = new Random();float f = r.nextFloat();stu.setId(f*1000+"id");stu.setName(f*10000+"name"+ s.getName());return stu;}
}class Stu{private String name;private String id;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getId() {return id;}public void setId(String id) {this.id = id;}
}

方法3

使用

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

底层使用了synchronized重量级锁,使其效率很低,所以对 ArrayList 的同步主要采用 CopyOnWriteArrayList

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

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

相关文章

V23 中的新增功能:LEADTOOLS React Medical Web 查看器

LEADTOOLS (Lead Technology)由Moe Daher and Rich Little创建于1990年&#xff0c;其总部设在北卡罗来纳州夏洛特。LEAD的建立是为了使Daher先生在数码图象与压缩技术领域的发明面向市场。在过去超过30年的发展历程中&#xff0c;LEAD以其在全世界主要国家中占有的市场领导地位…

游戏视频录制软件有哪些?这3款推荐给你

在数字化时代的今天&#xff0c;游戏视频录制已经成为广大游戏爱好者和职业玩家的必需品&#xff0c;那么游戏视频录制软件有哪些&#xff1f;哪个更适合您呢&#xff1f; 本文将为您推荐3款游戏视频录制软件&#xff0c;帮助您记录下游戏中的精彩瞬间&#xff0c;也可以通过录…

光伏风电智能互联:IEC104转MQTT网关解决方案

背景情况 IEC60870-5-104&#xff0c;是为适应电力系统&#xff0c;包括能源管理系统&#xff08;EMS&#xff09;、数据采集&#xff08;SCADA&#xff09;系统、配电自动化系统以及其他公用事业&#xff0c;安全监控而制定的传输规约。IEC104规约将IEC101的应用层与TCP/IP提…

鸿蒙内核源码分析(用栈方式篇) | 程序运行场地谁提供的

精读内核源码就绕不过汇编语言&#xff0c;鸿蒙内核有6个汇编文件&#xff0c;读不懂它们就真的很难理解以下问题. 1.系统调用是如何实现的? 2.CPU是如何切换任务和进程上下文的? 3.硬件中断是如何处理的? 4.main函数到底是怎么来的? 5.开机最开始发生了什么? 6.关机…

Allegro画PCB中如何旋转器件

PCB中如何旋转器件 鼠标点击器件&#xff0c;然后右击&#xff0c;选择“Rotate”&#xff0c;然后再“Options”里选择旋转的角度和旋转中心&#xff0c;如下图&#xff1a; 然后鼠标转动就可以转动器件了。

数据结构——时间复杂度与空间复杂度

文章目录 一、算法效率算法的复杂度 二、时间复杂度1.时间复杂度的概念2.大O的渐进表示法3.例子 三、空间复杂度1.空间复杂度概念2.例子 四、常见复杂度对比 一、算法效率 算法的复杂度 算法在编写成可执行程序后&#xff0c;运行时需要耗费时间资源和空间(内存)资源 。 因此…

【算法刷题 | 贪心算法07】4.29(用最少数量的箭引爆气球、无重叠区间)

文章目录 12.用最少数量的箭引爆气球12.1题目12.2解法&#xff1a;贪心12.2.1贪心思路12.2.2代码实现 13.无重叠区间13.1题目13.2解法&#xff1a;贪心13.2.1贪心思路13.2.2代码实现 12.用最少数量的箭引爆气球 12.1题目 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面…

python可视化图表

1.测试数据准备 2011年1月销售数据.txt 2011-01-01,4b34218c-9f37-4e66-b33e-327ecd5fb897,1689,湖南省 2011-01-01,5b6a6417-9a16-4243-9704-255719074bff,2353,河北省 2011-01-01,ae240260-68a9-4e59-b4c9-206be4c08a8d,2565,湖北省 2011-01-02,c833e851-880f-4e05-9de5-b5…

Flutter 有什么优异特性和革命性创新之处?

Flutter 有什么优异特性和革命性创新之处? 什么是 Flutter&#xff1f; Flutter mobile app SDK是一种新的方式来构建漂亮的原生移动应用程序&#xff0c;摆脱过去常见的“千篇一律”的应用程序。用过Flutter的人都对它赞赏有加&#xff1b; 相比较其他新型系统&#xff0c…

如何用揿针治疗慢性咽炎?

点击文末领取揿针的视频教程跟直播讲解 在日常生活中&#xff0c;慢性咽炎极为常见&#xff0c;不致命却很恼人。一旦发作&#xff0c;你的喉咙每天都会不舒服&#xff0c;总感觉有东西堵着&#xff0c;但是呢&#xff0c;咳又咳不出来&#xff0c;咽也咽不下去&#xff0c;你…

五一劳动节,祝你劳动快乐,休息更快乐!

五一国际劳动节亦称“五一节”&#xff0c;在每年的五月一日。此节源于美国芝加哥城的工人大罢工。Labour Day also known as "51" on May 1 of each year.This section comes from the city of Chicago workers strike. 1886年5月1日&#xff0c;芝加哥的二十一万六…

opencv_23_高斯模糊

void ColorInvert::gaussian_blur(Mat& image) { Mat dst; GaussianBlur(image, dst, Size(0, 0), 15); // Size(2, 2), imshow("图像模糊2", dst); }

最新CRM系统评测:发现双重功能的好用客户关系管理系统

对于绝大多数企业来说&#xff0c;拥有强大的销售能力是实现增长、获得收益的关键。在如今企业数字化的大背景下&#xff0c;我们经常会听到关于自动化的讨论&#xff0c;也有声音会说&#xff0c;企业数字化成功与否的标准之一就是自动化程度。销售自动化&#xff08;SFA&…

集成框架 -- OSS

前言 接入oss必须有这两个文档基础 使用STS临时访问凭证访问OSS_对象存储(OSS)-阿里云帮助中心 前端上传跨域 正文 sts前后端通用&#xff0c;开通图示 AliyunSTSAssumeRoleAccess 后端实现代码 public static void main(String[] args) {String regionId "cn-ha…

Emby Notifier——一个媒体通知推送服务

Emby Notifier 这是另一个项目 watchdog_for_Emby 的最新优化版本&#xff0c;取消了 nfo 文件的监视依赖&#xff0c;该版本不再需要手动设置媒体库路径&#xff0c;对通过网盘挂载生成的媒体库更加友好~ Emby Server 版本 (重要&#xff01;&#xff01;&#xff01;) 4.8.0…

【会员单位】浙江晧月水务科技有限公司

中华环保联合会理事单位 水环境治理专业委员会副主任委员单位 公司成立于2018年3月14日&#xff0c;是专业研究废水处理业务的国家高新技术企业。 公司自主研发的脱硫废水“零排放”的技术&#xff0c;不仅适应性好&#xff0c;技术先进&#xff0c;智慧化程度高&#xff0c…

Leetcode—1041. 困于环中的机器人【中等】

2024每日刷题&#xff08;121&#xff09; Leetcode—1041. 困于环中的机器人 实现代码 class Solution { public:bool isRobotBounded(string instructions) {int x 0;int y 0;int d 0;vector<vector<int>> direction{{0, 1}, {1, 0}, {0, -1}, {-1, 0}};for…

网络安全主题纪录片

网络安全主题纪录片 文章目录 网络安全主题纪录片第四公民黑客帝国系列龙纹身女孩碟中谍系列虎胆龙威4匿名者终结者2&#xff1a;审判日东方快车谋杀案黑客国家公敌我是谁&#xff1a;没有绝对安全的系统黑客军团速度与激情系列十亿美元大劫案勒索软件的背后黑客的恐惧为什么网…

Python实用记录(十六):PyQt/PySide6联动VSCode便捷操作指南

文章目录 一、安装vscode和配置pyside6环境二、安装vscode扩展三、扩展配置编辑四、编辑运行 一、安装vscode和配置pyside6环境 这一步默认已经通过了 二、安装vscode扩展 三、扩展配置编辑 四个地方需要修改&#xff1b;rcc路径、uic路径、designer.exe路径 uic.exe 用于将…

基于Docker + Locust的数据持久化性能测试系统

前几天给大家分享了如何使用Locust进行性能测试&#xff0c;但是在实际使用中会发现存在压测的结果无法保存的问题&#xff0c;比如在分布式部署情况下进行压测&#xff0c;每轮压测完成需要释放资源删除容器重新部署后&#xff0c;这段时间的压测结果就都丢失了&#xff0c;如…