首页 > 其他分享 >多线程-多个子线程执行结果插入List集合

多线程-多个子线程执行结果插入List集合

时间:2024-04-11 15:22:32浏览次数:16  
标签:Thread List list util 线程 import 多线程

业务场景:将多个子线程的执行结果存入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());
    }
}
执行结果:
![](/i/l/?n=24&i=blog/2317593/202404/2317593-20240411152158316-1276467749.png)
![](/i/l/?n=24&i=blog/2317593/202404/2317593-20240411152203336-2063481736.png)
![](/i/l/?n=24&i=blog/2317593/202404/2317593-20240411152210391-247759297.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());
    }
}
执行结果:
![](/i/l/?n=24&i=blog/2317593/202404/2317593-20240411152224807-905636934.png)
可以发现,线程执行数量和执行结果数量相等,这就是线程不安全带来的后果
总结:在并发给List进行修改时,可以使用Vector或者Collections.synchronizedList(),不要直接使用ArrayList,在非并发情况下尽量使用ArrayList;

标签:Thread,List,list,util,线程,import,多线程
From: https://www.cnblogs.com/itbs/p/18129279

相关文章

  • RecyclerView与ListView区别
    目录1.先说结论2.继承关系3.布局操作4.动画效果5.数据刷新方式6.缓存机制6.1ListView6.2 RecyclerView缓存实例1.先说结论RecyclerView是我们优先考虑的,已经规范化的,自带动画效果的,布局更多样的控件2.继承关系ListView-》继承BaseAdapter,需要自定义ViewHold......
  • ThreadPoolExecutor线程池解析
    ThreadPoolExecutor线程池解析一、ThreadPoolExecutor常见参数jdk中Executors提供了几种常用的线程池,底层都是ThreadPoolExecutor。publicThreadPoolExecutor(intcorePoolSize,//核心线程数intmaximumPoolSize,//最大线程数......
  • Java List集合去重、过滤、分组、获取数据、求最值、合并、排序、跳数据和遍历
    前言请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i、准备工作:现有一个User类、Student类和Ticket类,加入相关依赖@DatapublicclassUser{/***id*/privateIntegerid;/***姓名*/privateStringname;/**......
  • 多线程知识点
     1.多线程基本概念1)概念:多线程简单来说是一个程序具备同时执行多个功能的能力。在多线程中,这些功能被称为线程,每个线程都有自己的执行路径,它们可以并行(xíng)运行,同时共享程序的资源与内存。而在传统的单线程程序中,代码会顺序执行,一个任务完成后才会开始下一个任......
  • 单线程Reactor模型
    1.如何理解reactorreactor是一种设计模式。用于处理事件驱动的系统。reactor模式,主要有两个组件:reactor反应器:负责监听所有事件,当事件发生时,调用相应的处理程序。reactor本身时一个事件循环,负责处理I/O事件。handler处理程序:处理特点类型的事件。当reactor接收......
  • 多线程下写全局变量时,可借助sleep(0)让出cpu
    目录一个demo(对全局变量++)-->反汇编阅读cpu指令多个线程都去对全局变量++线程不挂起sleep(0)使线程挂起,让出cpu总结一下为啥不到10W?加锁版本近期在重读APUE,对unix下多线程有了新的理解用一个小demo来说明多线程下写全局变量时,让出cpu(使线程挂起)的重要性一个demo(对全局变量++)-......
  • 多线程(进阶篇&小白易懂版)
    文章目录多线程为什么要有多线程多线程案例线程通讯分传主线程通讯主传分关闭线程线程锁多线程概念:多线程就是多个线程同时工作的过程,我们可以将线程看作是程序的执行路径,每个线程都定义了一个独特的控制流,用来完成特定的任务。如果您的应用程序涉及到复杂且耗时的......
  • django simpleui 的list_display添加自定义列、显示图片 及alert弹窗的设置方法
    参考djangosimpleui的list_display添加自定义列、显示图片及alert弹窗的设置方法-CSDN博客环境:python:3.8.xDjango:3.2.xDjango-simpleui:2021.x先定义下模型#models.pyclassDog(models.Model):name=models.CharField(max_length=15,verbose_name='小狗名字')......
  • 用本小组项目中实际的例子来重现如下问题: 1、代码覆盖率对于“应该写但是没有写的代
    例子1-代码覆盖率无法检测资源管理问题:假设在移动充电桩应用中有一个负责与服务器通信的模块,它从服务器下载充电站的实时状态信息。开发者编写了一段代码来连接服务器、发送请求并接收响应数据,但是在处理完响应后,忘记关闭网络连接或释放相关资源:JavapublicclassChargingSta......
  • c++11实现线程池
    c++11实现线程池c++线程库thread创建线程和同步的方式jion,detach#include<iostream>#include<thread>voidprintf_hw(std::strings){ std::cout<<s<<"\n";}intmain(){ std::threada(printf_hw,"nihao"); //a.join();//同步 a.de......