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.hqwc.cn/news/221205.html

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

相关文章

【C/C++】如何不使用 sizeof 求数据类型占用的字节数

实现代码&#xff1a; #include <stdio.h>#define GET_TYPE_SIZE(TYPE) ((char *)(&TYPE 1) - (char *) & TYPE)int main(void) {char a a;short b 0;int c 0;long d 0;long long e 0;float f 0.0;double g 0.0;long double h 0.0;char* i NULL;print…

大语言模型损失函数详解

我们可以把语言模型分为两类&#xff1a; 自动回归式语言模型&#xff1a;自动回归式语言模型在本质上是单向的&#xff0c;也就是说&#xff0c;它只沿着一个方向阅读句子。正向&#xff08;从左到右&#xff09;预测&#xff1b;反向&#xff08;从右到左&#xff09;预测。…

第二十二章 解读pycocotools的API,目标检测mAP的计算COCO的评价指标(工具)

Pycocotools介绍 为使用户更好地使用 COCO数据集, COCO 提供了各种 API。COCO是一个大型的图像数据集&#xff0c;用于目标检测、分割、人的关键点检测、素材分割和标题生成。这个包提供了Matlab、Python和luaapi&#xff0c;这些api有助于在COCO中加载、解析和可视化注释。 …

【古诗生成AI实战】之二——项目架构设计

[1] 项目架构 在我们深入古诗生成AI项目的具体实践之前&#xff0c;让我们首先理解整个项目的架构。本项目的代码流程主要分为三个关键阶段&#xff1a; 1、数据处理阶段&#xff1b;   2、模型训练阶段&#xff1b;   3、文本生成阶段。 第一步&#xff1a;在数据处理阶段…

6.12找树左下角的值(LC513-M)

算法&#xff1a; 这道题适合用迭代法&#xff0c;层序遍历&#xff1a;按层遍历&#xff0c;每次把每层最左边的值保存、更新到result里面。 看看Java怎么实现层序遍历的&#xff08;用队列&#xff09;&#xff1a; /*** Definition for a binary tree node.* public clas…

mysql从库设置为只读

直奔主题&#xff0c;mysql设置为只读后&#xff0c;无法增删改。 设置命令&#xff1a; mysql> set global read_only1; #1是只读&#xff0c;0是读写 mysql> show global variables like %read_only%; 以下是相关说明&#xff1a; 1、对于数据库读写状态&#xf…

Nginx(八) aio sendfile directio 组合使用测试(1)

测试输出日志太多&#xff0c;文章篇幅太长&#xff0c;所以没法一次性发布&#xff0c;只能拆成两部分了。 Nginx(九) aio & sendfile & directio 组合使用测试(2) 还是依照惯例&#xff0c;先上结论&#xff1a; 1、当开启aio&#xff0c;关闭sendfile时&#xff0…

文件搜索工具HoudahSpot mac中文版特点

HoudahSpot mac是一款文件搜索工具&#xff0c;它可以帮助用户快速准确地找到文件和文件夹&#xff0c;支持高级搜索和过滤&#xff0c;同时提供了多种视图和操作选项&#xff0c;方便用户进行文件管理和整理。 HoudahSpot mac软件特点 高级搜索和过滤功能&#xff1a;软件支持…

HarmonyOS开发者工具DevEco Studio-汉化

HarmonyOS DevEco Studio 简介 下载安装及汉化 打开开发者工具 安装语言包重启 然后设置页搜索“chinese”&#xff0c;选中中文语言包&#xff0c;点击后面的install&#xff1b; 或者 汉化按照IDEA的汉法风格&#xff0c;需要安装插件重启就可以汉化&#xff0c;步骤为&…

[C/C++]数据结构 堆的详解

一:概念 堆通常是一个可以被看做一棵完全二叉树的数组对象,它是一颗完全二叉树,堆存储的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并且需要满足每个父亲结点总小于其子节点(或者每个父亲结点总大于其子节点) 堆可以分为两种: 小堆: 任意一个父亲节点都小于其子…

MySQL性能优化,SQL调优,SQL调优的手段

文章目录 对MySQL性能的优化的理解硬件和操作系统层面的优化架构设计层面的优化MySQL程序配置优化SQL优化 SQL调优有哪几种方式1.EXPLAIN2.SQL语句中IN包含的值不应过多3.SELECT语句务必指明字段名称4.当只需要一条数据的时候&#xff0c;使用limit 15.如果排序字段没有用到索引…

二叉树算法—后继节点

与其明天开始&#xff0c;不如现在行动&#xff01; 文章目录 1 后继节点1.1 解题思路1.2 代码实现 &#x1f48e;总结 1 后继节点 1.1 解题思路 二叉树节点结构定义如下&#xff1a; public static class Node { public int cal; public Node left; public Node right; public…