业务场景:将多个子线程的执行结果存入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 应用服务】用App Service部署运行 Vue.js 编写的项目,应该怎么部署运行呢?

    问题描述 用App Service部署运行 Vue.js 编写的项目,应该怎么部署运行呢? 问题解答 VUE通常是运行在客户端侧的JS框架. App Service 在这种场景中是以静态文件的形式提供 ...

  2. 【Azure 应用服务】App Service与Application Gateway组合使用时发生的域名跳转问题如何解决呢?

    问题描述 为App Service配置了应用服务网关(Application Gateway),并且为Application Gateway配置了自定义域名,通过浏览器访问时,出现域名跳转问题,由自定 ...

  3. RocketMQ(7) 消费幂等

    1 什么是消费幂等 当出现消费者对某条消息重复消费的情况时,重复消费的结果与消费一次的结果是相同的,并且多次消 费并未对业务系统产生任何负面影响,那么这个消费过程就是消费幂等的. 幂等:若某操作执行多 ...

  4. 使用内网nginx代理rancher

    需求: rancher 部署在 192.168.188.167服务器上 控制台访问地址 https://192.168.188.167:8443 在本地只有192.168.80.111有权限访问, 需 ...

  5. Codeforces Round 651 (Div. 2)C. Number Game(数学思维数论)

    C. Number Game 我们考虑那些状态是必胜态 我的回合时n为奇数(除1外),直接除以n则必胜 下面偶数的情况稍复杂 偶数我们能进行的操作只有除以一个奇数,需要考虑怎么把当前状态变为对手的必败 ...

  6. MySQL联接表总结笔记

    SQL最强的的工呢过之一就是能够在护具检索查询的执行中联结表,联结表利用SQL的select能执行的最重要的操作,很好的理解联结及其语法学习SQL的一个重要的组成部分. 在能够有效的使用联结前,必须了 ...

  7. .Net下的简易Http请求调用(Post与Get)

    http请求调用是开发中经常会用到的功能.在内,调用自有项目的Web Api等形式接口时会用到:在外,调用一些第三方功能接口时,也会用到,因为,这些第三方功能往往是通过http地址的形式提供的,比如: ...

  8. XAF EFCore 示例

    前言 在DEV官方建议创建新的XAF项目推荐选择EFCore时,我也第一时间创建了XAF的EFCore项目,这也是我第一次创建这个类型的项目,之前一直使用XPO,避免不了要对比一下.如果熟悉XPO但不 ...

  9. Csharp学习Linq

    Linq的学习 这里继续使用之前文章创建的学生类,首先简单介绍一下linq的使用. Student.cs public class Student { public int Id { get; set ...

  10. QGIS中下载遥感影像的Python代码片段

    1. 引言 QGIS是开源免费且好用的GIS软件,并且可以使用Python脚本来控制 这里主要使用的打开QGIS时启动内置的Python解释器,这个Python解释器可以访问iface接口从而实现对Q ...