多个线程处理不同的数据,等线程都完成后再进行下一步操作

现在有三个任务,三个任务之间没有关联关系,但是第四个任务要等前三个完成之后才能进行,于是使用多线程完成前三个任务节省时间

示例代码:

public void saveDataByOnlineTimeNew(LocalDateTime startTime, LocalDateTime endTime) {Objects.requireNonNull(startTime, "开始时间不能为空");Objects.requireNonNull(endTime, "结束时间不能为空");List<User> users = baseMapper.selectAllRightUser(startTime, endTime);if (users.isEmpty()) {return;}List<Integer> userIdList = users.stream().map(User::getId).collect(Collectors.toList());// 创建三个 CompletableFuture 分别处理三个列表CompletableFuture<List<ProUserStatisticsNew>> future1 = CompletableFuture.supplyAsync(() -> {List<ProUserStatisticsNew> proUserStatisticsNews = saveDataByOnlineTime(startTime, endTime, userIdList);users.parallelStream().forEach(user -> {log.trace("当前线程名字:"+Thread.currentThread().getName());List<ProUserStatisticsNew> versionNotInRelationList = this.saveDataByOnlineTimeByUser(startTime, endTime, user);if (!versionNotInRelationList.isEmpty()) {proUserStatisticsNews.addAll(versionNotInRelationList);}});return proUserStatisticsNews;});CompletableFuture<List<ProUserStatisticsNew>> future2 = CompletableFuture.supplyAsync(() -> saveNoVersionDataByOnlineTime(startTime, endTime, userIdList));CompletableFuture<List<ProUserStatisticsNew>> future3 = CompletableFuture.supplyAsync(() -> saveLearnDataByOnlineTime(startTime, endTime, userIdList));// 等待所有 CompletableFuture 完成CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);// 等待所有 CompletableFuture 完成后,进行合并操作CompletableFuture<List<ProUserStatisticsNew>> join = allFutures.thenApplyAsync(v ->mergeLists(future1.join(), future2.join(), future3.join()));List<ProUserStatisticsNew> result = join.join();//List<ProUserStatisticsNew> result = mergeLists(proUserStatisticsNews, noVersionDataList, learnDataList);SysConfigTime sysConfigTimeByTime = SysConfigTimeUtil.getSysConfigTimeByTimeForQuery(endTime);result.parallelStream().forEach(one -> {one.setRecordDate(sysConfigTimeByTime.getYearmonth());one.setProjectHoursDifference(one.getWorkHours().subtract(one.getActualHours()));});// 批量保存或更新int batchSize = 100; // 根据具体要求和系统能力设置适当的批处理大小for (int i = 0; i < result.size(); i += batchSize) {int end = Math.min(result.size(), i + batchSize);this.saveOrUpdateBatch(result.subList(i, end));}}

代码解析:

这段代码实现了一个方法 `saveDataByOnlineTimeNew`,它通过多个异步任务(使用 `CompletableFuture`)并行处理数据,并最终将结果批量保存或更新到数据库中。具体的逻辑流程可以分为几个部分,下面我会逐步解释每个部分。### 方法说明- **输入参数**: `startTime` 和 `endTime` 是查询的开始和结束时间(`LocalDateTime` 类型),指定了需要查询的数据范围。- **核心目标**: 这个方法的目标是根据 `startTime` 和 `endTime` 获取相关数据,并将结果合并后保存或更新到数据库。### 代码分析1. **非空检查**:```javaObjects.requireNonNull(startTime, "开始时间不能为空");Objects.requireNonNull(endTime, "结束时间不能为空");```这两行代码确保 `startTime` 和 `endTime` 不能为空。如果为 `null`,将抛出 `NullPointerException`,并带有指定的错误信息。2. **获取用户列表**:```javaList<User> users = baseMapper.selectAllRightUser(startTime, endTime);if (users.isEmpty()) {return;}```这里通过调用 `baseMapper.selectAllRightUser(startTime, endTime)` 查询所有符合条件的用户。如果查询结果为空,则直接返回,不进行后续处理。3. **获取用户 ID 列表**:```javaList<Integer> userIdList = users.stream().map(User::getId).collect(Collectors.toList());```使用 `stream` 获取所有用户的 ID,方便后续操作。4. **创建多个 `CompletableFuture`**:```javaCompletableFuture<List<ProUserStatisticsNew>> future1 = CompletableFuture.supplyAsync(() -> {// 异步任务1});CompletableFuture<List<ProUserStatisticsNew>> future2 = CompletableFuture.supplyAsync(() -> saveNoVersionDataByOnlineTime(startTime, endTime, userIdList));CompletableFuture<List<ProUserStatisticsNew>> future3 = CompletableFuture.supplyAsync(() -> saveLearnDataByOnlineTime(startTime, endTime, userIdList));```创建了三个异步任务,每个任务执行不同的操作:- **`future1`**:调用 `saveDataByOnlineTime` 来保存基于在线时间的数据,然后对每个用户并行处理数据,并将结果合并。- **`future2`**:调用 `saveNoVersionDataByOnlineTime` 来保存没有版本数据的数据。- **`future3`**:调用 `saveLearnDataByOnlineTime` 来保存学习数据。5. **等待所有异步任务完成**:```javaCompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2, future3);```使用 `CompletableFuture.allOf()` 来等待所有的 `future1`, `future2`, `future3` 完成。`allOf` 返回一个 `CompletableFuture<Void>`,表明所有任务已完成。6. **合并结果**:```javaCompletableFuture<List<ProUserStatisticsNew>> join = allFutures.thenApplyAsync(v ->mergeLists(future1.join(), future2.join(), future3.join()));```当所有的异步任务完成后,调用 `thenApplyAsync` 继续处理合并操作。`join` 方法会阻塞直到每个 `CompletableFuture` 返回结果,合并三个任务的结果列表。7. **结果后处理**:```javaList<ProUserStatisticsNew> result = join.join();SysConfigTime sysConfigTimeByTime = SysConfigTimeUtil.getSysConfigTimeByTimeForQuery(endTime);result.parallelStream().forEach(one -> {one.setRecordDate(sysConfigTimeByTime.getYearmonth());one.setProjectHoursDifference(one.getWorkHours().subtract(one.getActualHours()));});```- `join.join()` 等待合并操作完成,获得最终的 `result` 列表。- 使用 `SysConfigTimeUtil.getSysConfigTimeByTimeForQuery(endTime)` 获取系统配置的时间信息。- 对 `result` 列表中的每一项,设置其记录日期(`setRecordDate`)和工作时间差(`setProjectHoursDifference`)。8. **批量保存或更新**:```javaint batchSize = 100;for (int i = 0; i < result.size(); i += batchSize) {int end = Math.min(result.size(), i + batchSize);this.saveOrUpdateBatch(result.subList(i, end));}```为了避免一次性将大量数据写入数据库,采用批处理的方式分批保存或更新数据。每次处理 `batchSize` 条记录(这里设定为100),直到所有记录处理完。### 关键点总结- **异步任务并行执行**:使用 `CompletableFuture.supplyAsync()` 创建三个并行任务来处理数据,从而加快整个处理过程。
- **合并操作**:通过 `thenApplyAsync` 合并三个异步任务的结果。
- **批量操作**:为了提高性能,使用批量保存或更新的方法 `saveOrUpdateBatch`,避免一次性提交过多数据。### 性能优化
- 该方法使用了并行流 (`parallelStream()`) 和异步执行(`CompletableFuture`),这些可以显著提升性能,尤其是对于大规模数据的处理。
- 批量操作减少了数据库访问的次数,提高了数据库的写入效率。总的来说,这段代码实现了一个高效的数据处理和保存机制,使用了现代 Java 特性(如异步编程和流操作)来优化性能。

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

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

相关文章

Spring Boot自定义中文Banner

Spring Boot自定义中文Banner在线生成工具 https://www.bootschool.net/https://www.bootschool.net/1.选择喜欢的复制 2.在resources文件下新建banner文件&#xff0c;粘贴即可 <_> ::::: …

SpringCloud源码-Ribbon

一、Spring定制化RestTemplate&#xff0c;预留出RestTemplate定制化扩展点 org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration 二、Ribbon定义RestTemplate Ribbon扩展点功能 org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguratio…

风力涡轮机缺陷检测数据集,86.6%准确识别率,11921张图片,支持yolo,PASICAL VOC XML,COCO JSON格式的标注

风力涡轮机缺陷检测数据集&#xff0c;86.6&#xff05;准确识别率&#xff0c;11921张图片&#xff0c;支持yolo&#xff0c;PASICAL VOC XML&#xff0c;COCO JSON格式的标注 数据集下载 yolov11&#xff1a; https://download.csdn.net/download/pbymw8iwm/90206849 yolov…

Vue 针对浏览器参数过长实现浏览器参数加密解密

1、首先安装crypto-js npm install crypto-js 1、在router/index.js中添加如下代码 在utils工具类添加如下 encryption.js源码 import CryptoJS from crypto-js import CryptoJSCore from crypto-js/core import AES from crypto-js/aes import ZeroPadding from crypto-js/…

antdesignvue vue3全局loading

这里封装为loading.js文件&#xff0c;代码赋值即可用 import { createApp, h } from vue import { Spin } from ant-design-vuelet instance null// 定义全屏遮罩样式 const style {position: fixed,left: 0,top: 0,width: 100%,height: 100%,display: flex,justifyContent…

WPF的一些控件的触发事件记录

<c1:C1ComboBox Width"230" ItemsSource"{Binding ReplaceWayList}" Style"{StaticResource ListSearch-C1ComboBox}" SelectedValueChanged"C1ComboBox_SelectedValueChanged"&#xff0c; 下拉框事件&#xff0c;SelectedValu…

设计模式-创建型设计模式总结

创建型设计模式&#xff08;Creational Design Patterns&#xff09;是 设计模式 中的一类&#xff0c;专注于如何实例化对象或类。它们提供了一些优雅的方式来创建对象&#xff0c;允许程序在对象创建过程中更灵活地进行管理&#xff0c;从而提高系统的扩展性和维护性。 创建…

Transformer算法实现IMDB文本分类任务和WMT14机器翻译任务

Transformer算法详解与PyTorch实现 目录 Transformer算法详解与PyTorch实现1. Transformer算法简介1.1 Transformer的优势1.2 Transformer的应用场景2. Transformer的核心组件2.1 自注意力机制(Self-Attention)2.2 多头注意力机制(Multi-Head Attention)2.3 位置编码(Posi…

Python脚本实现通过Vector VN1630A CAN盒子与ECU通信

1 安装 python-can 包 安装命令如下&#xff1a; pip install python-can安装完成后可用下面命令查看是否安装成功及版本。 pip show python-canName: python-can Version: 4.4.2 Summary: Controller Area Network interface module for Python Home-page: https://github.…

React虚拟DOM:理解和应用

写在前面 在现代前端开发中&#xff0c;React 是一个非常流行的 JavaScript 库&#xff0c;用于构建用户界面。它引入了一个名为“虚拟 DOM”&#xff08;Virtual DOM&#xff09;的概念&#xff0c;这个概念对于 React 的高效性能和易用性至关重要。本文将深入探讨 React Vir…

VSCode 插件全解析:解锁编码新维度

文章目录 前言一、插件的重要性二、插件分类三、创建自己的插件结语 前言 Visual Studio Code&#xff08;简称 VSCode&#xff09;是一款由微软开发的免费开源文本编辑器&#xff0c;支持多种编程语言和各种扩展插件。它以其轻量级、跨平台和强大的可定制性而闻名&#xff0c…

Oracle 创建本地用户,授予权限,创建表并插入数据

目录 一. 用户的种类二. 切换session为PDB三. 创建用户并授予权限四. 创建表空间五. 为用户分配默认表空间并指定表空间配额六. 通过创建的用户进行登录七. 创建脚本&#xff0c;简化登录八. 查看用户信息九. 创建表&#xff0c;并插入数据9.1 查看当前用户的schema9.2 插入数据…

普及组集训数据结构--并查集

P1551 亲戚 - 洛谷 | 计算机科学教育新生态 并查集就是把所有相关联的量串成一串珠子&#xff0c;抽象来说就是&#xff1a; 把此类相关联的量当作节点&#xff0c;两个节点之间连接一条无向边&#xff0c;所形成的图 例题算法流程&#xff1a; 在此定义“族长”就是一个树的…

pytorch张量高级索引介绍

PyTorch 中&#xff0c;张量索引操作可以使用高级索引&#xff08;advanced indexing&#xff09;&#xff0c;其中索引可以是另一个张量。使用这种索引方式时&#xff0c;返回值的维度由索引张量的形状和原始张量的形状共同决定。以下是具体的规则和解释&#xff1a; 1. 基本…

ESP32-S3遇见OpenAI:OpenAI官方发布ESP32嵌入式实时RTC SDK

目录 OpenAI RTC SDK简介应用场景详解智能家居控制系统个人健康助手教育玩具 技术亮点解析低功耗设计快速响应高精度RTC安全性保障开发者指南 最近&#xff0c;OpenAI官方发布了一款针对ESP32-S3的嵌入式实时RTC&#xff08;实时时钟&#xff09;SDK&#xff0c;这标志着ESP32-…

JS基础 -- 数组 (对象 / 数组 / 类数组 / 对象数组)的遍历

一、数组&#xff1a; 数组是复杂数据类型&#xff0c;用于存储一组有序的数据。 1、创建数组&#xff1a; ① 使用 new 关键字&#xff1a; let arr new Array() // 创建一个长度为0的空数组 let arrLength new Array(5) // 创建一个长度为5的空数组② 字面量形式&#…

【期末复习】一、操作系统概论

题型 选择题 论述题 综合分析题(计算,证明) 算法分析题(根据程序代码分析) 1.方面 操作系统在计算机系统中主要涉及硬件、软件和数据这三个重要方面。 2.操作系统发展历史 手工操作阶段(1940s) 联机批处理系统阶段(1950s) 脱机批处理系统阶段(1950s) 多道…

基于STM32F103的USART的原理及应用(一)(实现手机BLE和MCU进行通信)

一&#xff0c;查阅数据手册&#xff0c;找到对应的IO口和外设总线并配置好外设源文件 想了解USART的具体原理的小伙伴请进传送门&#xff1a;&#xff08;总结&#xff09;STM32中USART原理及应用&#xff08;PC、BLE、ESP8266通信实现&#xff09;-CSDN博客 二&#xff0c;打…

如何在Java开发中选择适合的高性能工具库?

如何在Java开发中选择适合的高性能工具库&#xff1f; 在 Java 开发中选择适合的高性能工具库需要综合考虑多个因素&#xff0c;以下是详细的步骤和要点&#xff1a; 一、明确项目需求 功能需求 首先要确定项目需要的功能。例如&#xff0c;如果主要是进行 JSON 数据处理&a…

2025 小模型技术:驱动低代码与物联网融合发展新引擎

在科技的前沿赛道上&#xff0c;我们满怀期待地迈向 2025 年。这一年&#xff0c;小模型技术宛如一颗璀璨的新星&#xff0c;将在低代码与物联网的浩瀚星空中闪耀出独特光芒&#xff0c;成为引领二者融合发展的强劲引擎&#xff0c;为各行业的数字化变革带来澎湃动力与无限可能…