业务场景:将多个子线程的执行结果存入List,但是总会出现List集合的长度小于子线程的执行数的情况

1、错误示例(多个线程同时操作同一个List对象,List是线程不安全)

package unitTest;

import org.assertj.core.util.Lists;

import java.util.List;
import java.util.concurrent.CountDownLatch; public class ThreadTest {
public static void main(String[] args) throws InterruptedException { // 线程个数
int N = 5;
// 实例化一个倒计数器,N指定计数个数
CountDownLatch countDownLatch = new CountDownLatch(N); List<Thread> threadList = Lists.newArrayList();
List<String> list = Lists.newArrayList();
// List<String> list = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < N; i++) {
Thread thread = new Thread(()-> {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
list.add(Thread.currentThread().getName());
countDownLatch.countDown();
}); thread.start(); threadList.add(thread);
} // 阻塞,等待当计数减到0时,执行后面的代码
countDownLatch.await(); System.out.println("线程执行数量: "+threadList.size());
System.out.println("执行结果数量: "+list.size());
}
}
执行结果:
![](https://img2024.cnblogs.com/blog/2317593/202404/2317593-20240411150851346-683030106.png)
![](https://img2024.cnblogs.com/blog/2317593/202404/2317593-20240411150926356-1465132192.png)
![](https://img2024.cnblogs.com/blog/2317593/202404/2317593-20240411150949530-1899498542.png)
可以看见多次执行结果中,会存在执行结果集合数量小于线程执行总次数的情况 2、正确示例
1.使用Vector,是一个线程安全的List,但是它的线程安全实现方式是对所有操作都加上了synchronized关键字,这种方式严重影响效率.所以并不推荐使用Vector
2.使用 Collections.synchronizedList(List list),可以将add()等方法的时候是加synchronized关键字的,但是iterator()却没有加.所以在遍历使用的时候需要加上synchronized
```java
package unitTest; import org.assertj.core.util.Lists; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch; public class ThreadTest {
public static void main(String[] args) throws InterruptedException { // 线程个数
int N = 5;
// 实例化一个倒计数器,N指定计数个数
CountDownLatch countDownLatch = new CountDownLatch(N); List<Thread> threadList = Lists.newArrayList();
// List<String> list = Lists.newArrayList();
List<String> list = Collections.synchronizedList(new ArrayList<>());
for (int i = 0; i < N; i++) {
Thread thread = new Thread(()-> {
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
list.add(Thread.currentThread().getName());
countDownLatch.countDown();
}); thread.start(); threadList.add(thread);
} // 阻塞,等待当计数减到0时,执行后面的代码
countDownLatch.await(); System.out.println("线程执行数量: "+threadList.size());
System.out.println("执行结果数量: "+list.size());
}
}
执行结果:
![](https://img2024.cnblogs.com/blog/2317593/202404/2317593-20240411151401526-178989045.png)
可以发现,线程执行数量和执行结果数量相等,这就是线程不安全带来的后果

多线程-多个子线程执行结果插入List集合的更多相关文章

  1. netframework中等待多个子线程执行完毕并计算执行时间

    本文主要描述在.netframework中(实验环境.netframework版本为4.6.1)提供两种方式等待多个子线程执行完毕. ManualResetEvent 在多线程中,将ManualRes ...

  2. Java多线程理解:线程安全的集合对象

    1.概念介绍 线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用.不会出现数据不一致或者数据污染. 线程不安全就 ...

  3. CountDownLatch用法---等待多个线程执行完才执行

    CountDownLatch用法---等待多个线程执行完才执行 CountDownLatch用法---等待多个线程执行完才执行 CountDownLatch用法---等待多个线程执行完才执行 Coun ...

  4. C# 多线程join的用法,等待多个子线程结束后再执行主线程

    等待多个子线程结束后再执行主线程 class MultiThread{ #region join test public void MultiThreadTest() { Thread[] ths = ...

  5. Java多线程--让主线程等待所有子线程执行完毕

    数据量很大百万条记录,因此考虑到要用多线程并发执行,在写的过程中又遇到问题,我想统计所有子进程执行完毕总共的耗时,在第一个子进程创建前记录当前时间用System.currentTimeMillis() ...

  6. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  7. Java多线程——<三>简单的线程执行:Executor

    一.概述 按照<Java多线程——<一><二>>中所讲,我们要使用线程,目前都是显示的声明Thread,并调用其start()方法.多线程并行,明显我们需要声明多个 ...

  8. java多线程实现主线程等待子线程执行完问题

    本文介绍两种主线程等待子线程的实现方式,以5个子线程来说明: 1.使用Thread的join()方法,join()方法会阻塞主线程继续向下执行. 2.使用Java.util.concurrent中的C ...

  9. Java多线程系列四——控制线程执行顺序

    假设有线程1/线程2/线程3,线程3必须在线程1/线程2执行完成之后开始执行,有两种方式可实现 Thread类的join方法:使宿主线程阻塞指定时间或者直到寄生线程执行完毕 CountDownLatc ...

  10. 【Java多线程系列四】控制线程执行顺序

    假设有线程1/线程2/线程3,线程3必须在线程1/线程2执行完成之后开始执行,有两种方式可实现 Thread类的join方法:使宿主线程阻塞指定时间或者直到寄生线程执行完毕 CountDownLatc ...

随机推荐

  1. 【Azure Developer】使用 Powershell az account get-access-token 命令获取Access Token (使用用户名+密码)

    问题描述 在上篇的文章中,我们使用了JAVA SDK,根据用户名和密码来获取Azure AD的Access Token,这节,我们将使用Powershell az 命令来获取Access Token. ...

  2. 【Azure 存储服务】Azure Blob下面是否可以创建子文件夹

    问题描述 如何在Azure Storage Account(存储账户) 门户上为 Container 创建子文件夹? 问题解决 经验证,没有办法在门户上直接创建文件夹,不过可以使用Azure Stor ...

  3. Java 多线程----- 解决线程安全问题的 方式三:Lock锁 --------jdk 5.0 新增

    1 package bytezero.deadlock; 2 3 import java.util.concurrent.locks.ReentrantLock; 4 5 /** 6 * 解决线程安全 ...

  4. Mac上LLAMA2大语言模型安装到使用

    LLAMA介绍 LLaMA是由Facebook的母公司Meta AI设计的一个新的大型语言模型.LLaMA拥有70亿到650亿个参数的模型集合,是目前最全面的语言模型之一. Llama是目前唯一一个可 ...

  5. 学习笔记:勒让德(Legendre)符号

    授课老师:ybx.chh. 授课时间:2024/3/8. 授课内容纲要:勒让德符号及其性质(欧拉准则,高斯引理,二次互反律). 勒让德符号概括 好像在 OI 和 MO 当中都挺有用的. 勒让德符号的定 ...

  6. 摆脱鼠标系列 - vscode 左右切换文档 快捷键换成 Ctrl + Alt + 左右箭头

    为什么 默认快捷键是 Ctrl + PageUp PageDown 用的不太习惯 Ctrl + Alt + 左右箭头 和 双列的快捷键冲突了,那个就不用了,基本没用过 备份图

  7. idea vue 格式化 并保存文件 宏 快捷键 ctrl+s

    idea 格式化是 reformat Code 存盘是 ctrl+s 所以创建一个宏,先点格式化,再点存盘,然后定义个ctrl+s的快捷键覆盖之前的保存就ok了. 资料: IDEA 配置宏定义 并为宏 ...

  8. 在Linux平台使用wps卡顿现象解决方法

    是因为软件占据的内存过多,需要关掉目前不使用的软件,以释放系统内存.

  9. 基于可穿戴的GPS定位存储模块方案特色解析

    前记   GPS作为一个位置定位手段,在日常生活中扮演着非常重要的角色.在研发动物可穿戴产品的同时.团队一直在做产品和模块标准化的事情,尽量把研发出来的东西标准化.按照任老板的说法,在追求理想主义的路 ...

  10. 《TencentNCNN系列》 之工作原理简要解析(以LeNet-5为例)

    PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明   本文作为本人csdn blog的主站的备份.(Bl ...