CountDownLatch实战应用——批量数据多线程协调异步处理(主线程执行事务回滚)

😊 @ 作者: 一恍过去
💖 @ 主页: https://blog.csdn.net/zhuocailing3390
🎊 @ 社区: Java技术栈交流
🎉 @ 主题: CountDownLatch实战应用——批量数据多线程协调异步处理(主线程执行事务回滚)
⏱️ @ 创作时间: 2023年11月26日

在这里插入图片描述

目录

  • 前言
  • 1、概述
  • 2、实现
  • 3、方法说明:
  • 4、代码实例

前言

通过CountDownLatch开启多个子线程,由子线程完成数据的处理,最后由主线程进行数据库操作,由主线程进行事务的提交或者回滚;
如果需要由子线程处理完数据,并且由子线程进行事务提交或者回滚,参考:https://lhz1219.blog.csdn.net/article/details/134630509

1、概述

CountDownLatch是一个同步器工具类,用来协调多个线程之间的同步,能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行,不可重置使用。

2、实现

使用一个计数器进行实现,计数器初始值为线程的数量,当每一个线程完成自己任务后,计数器的值就会减一,当计数器的值为0时,在CountDownLatch上等待的线程就可以恢复执行接下来的任务。

3、方法说明:

  • public void countDown():递减锁存器的计数,如果计数到达零,则释放所有等待的线程。如果当前计数大于零,则将计数减少.
  • public viod await() /boolean await(long timeout,TimeUnit unit) :使当前线程在锁存器倒计数至零之前一直等待,除非线程被中断或超出了指定的等待时间。如果当前计数为零,则此方法立刻返回true值。当线程调用了CountDownLatch对象的该方法后,当前线程会被阻塞,直到下面的情况之一发生才会返回:
    • 如果计数到达零,则该方法返回true值。
    • 如果当前线程,在进入此方法时已经设置了该线程的中断状态;或者在等待时被中断,则抛出InterruptedException,并且清除当前线程的已中断状态。
    • 如果超出了指定的等待时间,则返回值为false。如果该时间小于等于零,则该方法根本不会等待。参数:timeout-要等待的最长时间、unit-timeout 参数的时间单位

4、代码实例

有用到hutool的工具包,pom如下:

        <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.0.7</version></dependency>

Controller:

@RestController
@RequestMapping("/test")
@Slf4j
public class TestController {@Resourceprivate CountDownService countDownService;/*** CountDownLatch实现多线程(多个子线程)异步处理数据,再主线程回归处理** @return*/@ApiOperation(value = "测试CountDownLatch", notes = "测试")@GetMapping("/countDown/handleData")public String countDownHandleData() {countDownService.handleData();return "success";}

Sevice:

@Service
@Slf4j
public class CountDownService {@Resourceprivate TestMapper testMapper;@Resourceprivate ApplicationContext applicationContext;/*** 实现多线程(多个子线程)异步处理数据,再主线程回归处理*/@Transactional(rollbackFor = Exception.class)public void handleData() {List<TestEntity> testList = getData();AtomicBoolean errorTag = new AtomicBoolean(false);long start = System.currentTimeMillis();// 使用多线程对list集合进行分批次处理,实际情况可以根据具体耗时来决定// 比如:一万条数据,每条单独处理需要200ms,按批次一个线程处理200条数据,分为50个批次,实际情况根据业务来定// 需要使用hutool工具类List<List<TestEntity>> splitList = CollUtil.split(testList, 200);// 设置countDown大小CountDownLatch countDownLatch = new CountDownLatch(splitList.size());// 简单创建一个线程池,这里的线程池可以自定义,为了方便直接使用ExecutorService executorService = Executors.newCachedThreadPool();splitList.forEach(list -> {// 线程处理executorService.execute(() -> {try {for (TestEntity entity : list) {if (errorTag.get()) {break;}// 对实体类的业务处理,此处模拟业务处理,耗时50msThreadUtil.sleep(50);// 模拟数据处理中,出现了异常if (entity.getCount().equals(2000)) {throw new RuntimeException("子线程执行异常");}}} catch (Exception e) {log.error("子线程异常:{}", e.getMessage(), e);errorTag.set(true);} finally {// 子线程中,业务处理完成后,利用countDown的特性,计数器减一操作countDownLatch.countDown();}log.info("子线程执行完成");});});executorService.shutdown();try {// 主线程阻塞countDownLatch.await();// 可以设置最大阻塞时间,防止线程一直挂起/*  boolean await = countDownLatch.await(5, TimeUnit.SECONDS);if (!await) {// 超过时间子线程都还没有结束,直接都回滚errorTag.set(true);}*/// 模拟执行主线程业务逻辑,比如insert、update等ThreadUtil.sleep(20);} catch (Exception e) {errorTag.set(true);}long end = System.currentTimeMillis();log.info("数据处理完成,耗时:{}", (end - start) / 1000);// 如果出现异常if (errorTag.get()) {throw new RuntimeException("异步业务执行出现异常");}log.info("主线程执行完成");}/*** 模拟解析的excel等文件的数据*/private List<TestEntity> getData() {List<TestEntity> list = new ArrayList<>();// 此处模拟一万条数据for (int i = 1; i <= 10000; i++) {TestEntity entity = new TestEntity();entity.setId(new Random().nextInt(999999999));entity.setCount(i);entity.setCommodityCode("code-" + i);entity.setMoney(new Random().nextInt(1000000));entity.setUserId("user-" + i);list.add(entity);}return list;}
}

在这里插入图片描述

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

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

相关文章

图像分割模型及架构选型介绍(MMSegmentation|sssegmentation等)

参考&#xff1a; https://zhuanlan.zhihu.com/p/618226513 0. 图像分割概述 图像分割通过给出图像中每个像素点的标签&#xff0c;将图像分割成若干带类别标签的区块&#xff0c;可以看作对每个像素进行分类。图像分割是图像处理的重要组成部分&#xff0c;也是难点之一。随…

C++如何实现自定义的struct作为unordered_set、unordered_map的key?

有两种方法&#xff1a; 1、自定义新struct的hash函数&#xff0c;和操作符&#xff0c;使用的时候需要指定unordered_set的第三个模板参数&#xff1a; #include <iostream> #include <unordered_map>struct MyStruct {std::string name;int id;// 自定义哈希函数…

OpenGL 自学总结

前言&#xff1a; 本人是工作后才接触到的OpenGL&#xff0c;大学找工作的时候其实比较着急&#xff0c;就想着尽快有个着落。工作后才发现自己的兴趣点。同时也能感觉到自己当前的工作有一点温水煮青蛙的意思&#xff0c;很担心自己往后能力跟不上年龄的增长。因此想在工作之余…

3DCAT为华东师大设计学院打造元宇宙数字虚拟学院

6月11日&#xff0c;华东师范大学设计学院在chi K11美术馆举办了一场别开生面的 2023 年本科毕业设计暨项目实践教学现场演示展。其中&#xff0c;元宇宙数字虚拟学院&#xff08;一期&#xff09;的现场发布会引起了现场震撼&#xff0c;吸引了众多观众的目光和参与。 该元宇宙…

MYSQL 连接的使用

文章目录 前言连接介绍在命令提示符中使用 INNER JOINMySQL LEFT JOINMySQL RIGHT JOIN在PHP脚本中使用JOIN后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Mysql &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握…

【Windows】执行tasklist/taskkill提示“错误:找不到”或者“ERROR: not found”的解决方案

原因 由于WinMgmt异常导致起不来&#xff0c;而WinMgmt是SVCHOST进程中的WMI服务&#xff0c;解决这个问题需要停止之后再重新启动。 WinMgmt是Windows 2000客户端管理的核心组件&#xff0c;当客户端应用程序连接或当管理程序需要它本身的服务时&#xff0c;这个进程就会初始…

【挑战业余一周拿证】二、在云中计算 - 第 1 节 - 模块2 简介

第 1 节 - 模块2 简介 无论你的企业是属于像医疗、保健、制造、保险等等行业 , 再或者 , 您的服务是向全世界的数百万用户提供视频、、图片或者文字服务,你也需要服务器来为您的业务和应用程序提供支持,服务器的作用是帮助您托管应用程序并提供满足您业务需求的计算能力. 当你使…

XML Schema 的extension 元素

XML Schema 的extension 元素对complexContent、simpleContent元素进行扩展。 例如&#xff0c;下面通过增加了两个属性&#xff0c;对simpleContent进行了扩展&#xff1a; <xs:element name"condition" maxOccurs"unbounded" minOccurs"0"…

Vue框架学习笔记——计算属性

文章目录 前文提要代码需求描述插值语法实现methods实现 计算属性getter执行时间&#xff1a;setter 计算属性简写形式&#xff08;只读不改&#xff0c;才能如此简写&#xff09;slice截取元素&#xff0c;限制输入字符数量 前文提要 本人仅做个人学习记录&#xff0c;如有错…

Leetcode 2939. Maximum Xor Product

Leetcode 2939. Maximum Xor Product 1. 解题思路2. 代码实现3. 代码优化&#xff1a; 题目链接&#xff1a;2939. Maximum Xor Product 1. 解题思路 这一题思路上来说我们就是逐位进行考虑。 对于xor操作&#xff0c;显然我们只有以下两种情况&#xff1a; 00或者11&…

【brpc学习实践九】mbvar及bvar可观测

概念、学习地址 mbvar中有两个类&#xff0c;分别是MVariable和MultiDimension&#xff0c;MVariable是多维度统计的基类&#xff0c;MultiDimension是派生模板类。也是主要用来多多线程计数用的。这里用到再详细去了解即可 https://github.com/luozesong/brpc/blob/master/do…

知识的分层:know-what/how/why

知识&#xff08;knowledge&#xff09;表示知道某些信息。通常而言&#xff0c;知识是正确的&#xff0c;但不一定是完备的。知识本身有自己的适用范围&#xff0c;特别是工程技术类问题。 根据知识的类型&#xff0c;可分为三类&#xff1a; know-whatknow-howknow-why kno…

Java多线程二-线程安全

1、线程安全问题 多个线程&#xff0c;同时操作同一个共享资源的时候&#xff0c;可能会出现业务安全问题。 2、实例&#xff1a;取钱的线程安全问题 2.1、场景 小明和小红是夫妻&#xff0c;他们有个共同账户&#xff0c;余额是十万元&#xff0c;如果两人同时取钱并且各自取…

vue3-10

动态路由与菜单 路由文件 a6router.ts import { createRouter, createWebHashHistory } from "vue-router"; import { useStorage } from "vueuse/core"; import { Route, Menu } from "../model/Model8080"; const clientRoutes [{path: &q…

nginx的一些命令

linux start nginx 开启 /usr/sbin/nginx&#xff08;直接启动&#xff09; nginx -s stop 停止 /usr/local/nginx/sbin/nginx -s stop nginx -s quit 安全停止&#xff0c;保存信息 nginx -s reload 当配置信息修改&#xff0c;需要重新载入这些配置时使用此命令 nginx -s re…

MATLAB|交叉折线图之间分色填充

目录 公众号 效果图 交叉折线图之间分色填充概念介绍 应用领域 优点 缺点

Linux内核--内存管理(二)物理内存分页机制

一、引言 二、物理内存模型 ------>2.1、平坦内存模型(Flat Memory Model) ------>2.2、对称多处理 SMP(Symmetric MultiProcessing) ------>2.3、非均衡访存模型 NUMA(Non-Uniform Memory Access) 三、节点、区域和页 ------>3.1、节点 ------>3.2、区域…

Python 安装mysqlclient 错误 无法打开包括文件: “mysql.h”: 解决方法

解决方案&#xff1a;python最新3.12.0不支持mysqlclient 请下载 python3.9.9 版本 高速下载地址CNPM Binaries Mirror 官方下载地址Welcome to Python.org 下载完成后将python添加到环境变量 pycharm 虚拟环境下的python版本切换到你刚才下载的3.9.9的python版本 Avai…

C#文件操作File类vsFileInfo类和Directory类vsDirectoryInfo类

目录 一、File类vsFileInfo类 1.File类 &#xff08;1&#xff09;示例源码 &#xff08;2&#xff09;生成效果 2.FileInfo类 &#xff08;1&#xff09;示例源码 &#xff08;2&#xff09;生成效果 二、 Directory类vsDirectoryInfo类 1.Directory类 &#xff08;…

FilterChain攻击解析及利用

文章目录 BASE64解码和编码原理浅析EncodingDecoding Filterchain构造&#xff08;原理阐述&#xff09;回顾死亡代码特性一&#xff08;双重去杂&#xff09;特性二&#xff08;粘合性&#xff09; 任意字符构造工具一工具二 实战例题[NSSRound#7 Team]brokenFilterChain&…