使用多线程往LIST添加数据 线程安全list

article/2025/8/24 8:22:08

我们在日常写代码的过程中,经常会使用多线程提高效率,我们在使用多线程过程中难免会出现往List集合修改数据。
下面我们来尝试一下往ArrayList 添加数据:

public static void main(String[] args) {List<Integer> list = new ArrayList<>();for (int i = 10000000; i >= 1; i--) {list.add(0);}System.out.println("源集合数量:"+list.size());List<Integer> newList = new ArrayList<>();long start = System.currentTimeMillis();ExecutorService executor = Executors.newFixedThreadPool(100);for (Integer integer : list) {executor.submit(()->{newList.add(integer+1);});}executor.shutdown();try {executor.awaitTermination(6, TimeUnit.MINUTES);} catch (InterruptedException e) {e.printStackTrace();}long end = System.currentTimeMillis();System.out.println("时间:"+(end-start)+"ms");System.out.println("新集合数量:"+newList.size());
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

我们使用线程池给 ArrayList 添加一千万个元素。来看下结果:

在这里插入图片描述

会发现新List’的数据会少于一千万,这是为什么呢?

因为 ArrayList 不是线程安全的,在高并发情况下对list进行数据添加会出现数据丢失的情况。
并且一个线程在遍历List,另一个线程修改List,会报ConcurrentModificationException(并发修改异常)错误

那么如果我们确实需要 并发对数据进行操作,并且对结果进行收集处理,应该怎么做呢?
一,使用Vector

在这里插入图片描述


从源码介绍里面我们可以看出 Viector是线程安全的,但后面也说明了,如果对线程安全没有要求,建议使用ArrayList,因为ArrayList单分效率更高。
从源码里面可以看到:

/*** Sets the size of this vector. If the new size is greater than the* current size, new {@code null} items are added to the end of* the vector. If the new size is less than the current size, all* components at index {@code newSize} and greater are discarded.** @param  newSize   the new size of this vector* @throws ArrayIndexOutOfBoundsException if the new size is negative*/public synchronized void setSize(int newSize) {modCount++;if (newSize > elementCount) {ensureCapacityHelper(newSize);} else {for (int i = newSize ; i < elementCount ; i++) {elementData[i] = null;}}elementCount = newSize;}/*** Returns the current capacity of this vector.** @return  the current capacity (the length of its internal*          data array, kept in the field {@code elementData}*          of this vector)*/public synchronized int capacity() {return elementData.length;}/*** Returns the number of components in this vector.** @return  the number of components in this vector*/public synchronized int size() {return elementCount;}/*** Tests if this vector has no components.** @return  {@code true} if and only if this vector has*          no components, that is, its size is zero;*          {@code false} otherwise.*/public synchronized boolean isEmpty() {return elementCount == 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

Vector里面的操作方法,都加上了synchronized 关键字。下面来使用Vector走一遍代码:

public static void main(String[] args) {List<Integer> list = new ArrayList<>();for (int i = 10000000; i >= 1; i--) {list.add(0);}System.out.println("源集合数量:"+list.size());List<Integer> newVector = new Vector<>();long start = System.currentTimeMillis();ExecutorService executor = Executors.newFixedThreadPool(100);for (Integer integer : list) {executor.submit(()->{newVector.add(integer+1);});}executor.shutdown();try {executor.awaitTermination(6, TimeUnit.MINUTES);} catch (InterruptedException e) {e.printStackTrace();}long end = System.currentTimeMillis();System.out.println("时间:"+(end-start)+"ms");System.out.println("newVector数量:"+newVector.size());}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

看下结果:

在这里插入图片描述


我们可以发现现在,新Vector里面的数量正好是一千万个。但是时间上要长于ArrayList。

二、使用Collections.synchronizedList()进行包装

public static void main(String[] args) {List<Integer> list = new ArrayList<>();for (int i = 10000000; i >= 1; i--) {list.add(0);}System.out.println("源集合数量:"+list.size());/*** Collections.synchronizedList()包装*/List<Integer> newCollList = Collections.synchronizedList(new ArrayList<>());long start = System.currentTimeMillis();ExecutorService executor = Executors.newFixedThreadPool(100);for (Integer integer : list) {executor.submit(()->{newCollList.add(integer+1);});}executor.shutdown();try {executor.awaitTermination(6, TimeUnit.MINUTES);} catch (InterruptedException e) {e.printStackTrace();}long end = System.currentTimeMillis();System.out.println("时间:"+(end-start)+"ms");System.out.println("newCollList新集合数量:"+newCollList.size());}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

结果:

在这里插入图片描述


我们可以发现也是一千万条。时间上和Vector差距不大,因给给ArrayList进行了包装以后等于是给ArrayList里面所有的方法都加上了 synchronized,和Vector实现效果差不多。

总结:在并发给List进行修改时,可以使用Vector或者Collections.synchronizedList(),不要直接使用ArrayList,在非并发情况下尽量使用ArrayList;

版权声明:本文为flycp原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

本文链接:使用多线程往List添加数据_cpown的博客-CSDN博客_多线程向list添加元素


http://chatgpt.dhexx.cn/article/KJi61tSI.shtml

相关文章

集合线程安全

集合线程安全 常用的集合类型如ArrayList&#xff0c;HashMap&#xff0c;HashSet等&#xff0c;在并发环境下修改操作都是线程不安全的&#xff0c;会抛出java.util.ConcurrentModificationException异常&#xff0c;这节主要记录如何在并发环境下安全地修改集合数据。 List…

线程安全的遍历list

遍历List的多种方式 在讲如何线程安全地遍历List之前&#xff0c;先看看通常我们遍历一个List会采用哪些方式。 方式一&#xff1a; for(int i 0; i < list.size(); i) {System.out.println(list.get(i)); } 方式二&#xff1a; Iterator iterator list.iterator(); while…

List的线程安全

List的线程安全 背景实验1. ArrayList2. synchronizedList3. 运行抛出异常ArrayIndexOutOfBoundsException异常原因 背景 Q&#xff1a;今天遇到一个场景&#xff0c;我们业务需要使用批量的数据进行操作&#xff0c;但是别人的接口只支持一个一个的查&#xff0c;所以需要用多…

线程安全 List 效率测试

List 常见类以及各自优缺点可自行参考 https://blog.csdn.net/weixin_39883065/article/details/111197724 本机环境 java 版本&#xff1a;1.8.0_161 window 信息&#xff1a; 测试代码 下面通过代码测试 List 线程安全类 Vector、Collections.synchronizedList(List lis…

三种线程安全的List

在单线程开发环境中&#xff0c;我们经常使用ArrayList作容器来存储我们的数据&#xff0c;但它不是线程安全的&#xff0c;在多线程环境中使用它可能会出现意想不到的结果。 多线程中的ArrayList&#xff1a; 我们可以从一段代码了解并发环境下使用ArrayList的情况&#xff…

线程安全的List

线程安全的List Vector类的架构基本属性构造方法基本方法 SynchronizedList和SynchronizedRandomAccessListCollections.synchronizedList构造方法具体方法具体使用 CopyOnWriteArrayList(**)简介结构成员变量常见方法add (***)removeget CopyOnWriteArrayList总结 总结 在我们…

Git - 拉取远程分支并创建本地分支

一、查看远程分支 使用如下git命令查看所有远程分支 git branch -r 查看远程和本地所有分支 git branch -a 查看本地分支 git branch 在输出结果中&#xff0c;前面带* 的是当前分支 二、拉取远程分支并创建本地分支 方法一 使用如下命令 git checkout -b 本地分支名…

Git获取远程分支文件并创建自己的远程分支

Git获取远程分支文件并创建自己的远程分支 1、前期准备软件&#xff1a;git-bash 2、获取远程分支文件过程 创建一个空的文件夹&#xff0c;选择文件夹&#xff0c;并右击&#xff0c;选择该选项打开命令行。 复制需要拉取的远程仓库地址。 &#xff08;2&#xff09;把maste…

git基于远程分支创建本地分支

git基于远程分支创建本地分支 1.首先 git branch -a 查看所有的分支 2.使用 git checkout -b 本地分支名 远程分支名 https://blog.csdn.net/north1989/article/details/116299912?utm_mediumdistribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm1001.…

git 创建本地分支及远程分支并且关联分支

git命令在创建本地分支及远程分支并且关联远程分支 为了便于版本的维护及管理将会不断的在master分支上创建出新的分支 大致分为: 首先切换到在要开的分支上――――>创建本地分支――――>创建远程分支――――>切换到本地分支――――>将本地分支与远程分支关联…

git 创建远程分支,并提交代码到该分支的操作

1. 首先&#xff0c;在本地创建这个分支 使用命令 git checkout -b 分支名 &#xff08;表示创建这个分支&#xff0c;并且切换到该分支&#xff09; 2. 创建远程分支 使用命令 git push --set-upstream origin 分支名 &#xff08;表示将分支推送到远程仓库&#xff09; 3. …

git创建远程分支并关联本地分支

场景一&#xff1a; 本地、远程都没有分支 "v1.0.0" 1. 先查看确认一下&#xff0c;命令&#xff1a; git branch -a 2. 创建本地分支&#xff0c;命令&#xff1a; git checkout -b v1.0.0 3. 创建远程分支&#xff0c;并且本地分支关联远程分支&#xff0c;命令…

Git 创建远程分支并提交代码到远程分支

1、可以通过git branch -r 命令查看远端库的分支情况 2、从已有的分支创建新的分支(如从master分支),创建一个dev分支 但此时并没有在远程仓库上创建分支 如图所示 还是只有一个master分支 3、建立本地到远端仓库的链接 --这样代码才能提交上去 使用命令行 git push --set-…

Git创建远程分支并提交代码到远程分支

1、可以通过git branch -r 命令查看远端库的分支情况 动图演示&#xff08;选择项目右键选择 Git Bash Here&#xff0c;然后输入命令git branch -r&#xff09;&#xff1a; 2、从已有的分支创建新的分支(如从master分支),创建一个dev分支 但此时并没有在远程仓库上创建分支 如…

机器学习知识经验分享之三:基于卷积神经网络的经典目标检测算法

文章目录 前言一、一阶段目标检测算法1.YOLO系列算法2.SSD检测算法3. RetinaNet检测算法 二、两阶段目标检测算法1.Faster R-CNN检测算法2.Mask R-CNN检测算法3.Cascade R-CNN检测算法 总结 前言 本系列文章将对机器学习知识进行分享总结。便于大家从理论层面了解人工智能基础…

轻量型目标检测算法一次看个够

序言 不知道大家有没有发现&#xff0c;近两年目标检测算法发展非常的快&#xff0c;恍惚一看&#xff0c;单阶段算法几乎统一了目标检测&#xff0c;各种高性能的目标检测算法层出不穷&#xff0c;印象中是在YOLOv4出来后&#xff0c;基于YOLO的改进变得一发不可收拾&#xf…

万字长文概述单目3D目标检测算法

一&#xff0c;理论基础-相机与图像 相机将三维世界中的坐标点&#xff08;单位为米&#xff09;映射到二维图像平面&#xff08;单位为像素&#xff09;的过程能够用一个几何模型进行描述&#xff0c;这个模型有很多种&#xff0c;其中最简单的称为针孔相机模型。相机的成像过…

yolov5 目标检测算法

简介&#xff1a; 目标检测在生活中应用领域非常广泛&#xff0c;列如&#xff1a;道路违规抓拍、未戴口罩识别、工地未佩戴安全帽抓拍、厨房出现老鼠检测。 还可以用在游戏辅助外挂。以枪战为例&#xff0c;在游戏过程中时刻检测有没有人头出现。当检测到目标人头&#xff0c;…

【快速入门】YOLOv5目标检测算法

文章目录 一、YOLOv5简介二、网络结构1、Input2、Backbone3、Neck4、Head 三、改进方法1、自适应锚框计算2、自适应灰度填充 四、性能表现五、YOLOv5入门实战 一、YOLOv5简介 YOLOv5是一个在COCO数据集上预训练的物体检测架构和模型系列&#xff0c;它代表了Ultralytics对未来…

目标检测算法汇集介绍

目标检测算法 目标检测概念 目标检测这里阐述两个应用场景&#xff0c;1 为物体位置检测&#xff0c;2 为物体关键点检测。 1 物体位置检测 相比与图片分类&#xff0c;目标检测算法结果要求不仅识别出图片中的物理类别并且输出物体的位置参数。 物体的位置通过bounding bo…