当前位置: 首页 > news >正文

性能优化实战使用CountDownLatch

1.分析问题

原程序是分页查询EventAffinityScoreDO表的数据,每次获取2000条在一个个遍历去更新EventAffinityScoreDO表的数据。但是这样耗时比较慢,测试过30万的数据需要2小时

  private void eventSubjectHandle(String tenantId, String eventSubject) {// 查询eventAffinityScoreDO表,更新时间小于今天的(今天更新过的不更新)final Integer pageSize = 2000;PageResult<EventAffinityScoreDO> groupPag =eventAffinityScoreDbService.findByTenantIdAndTimePage(tenantId, eventSubject, 1, pageSize);Integer pages = groupPag.getPages();Integer pageNum = groupPag.getPageNum();while (pages >= pageNum) {if (pageNum > 1) {groupPag =eventAffinityScoreDbService.findByTenantIdAndTimePage(tenantId, eventSubject, 1, pageSize);}List<EventAffinityScoreDO> list = groupPag.getList();forEventAffinityScore(tenantId, eventSubject, list);if (list.size() < pageSize) {break;}pageNum++;}}private void forEventAffinityScore(String tenantId, String eventSubject, List<EventAffinityScoreDO> eventAffinityScoreDOS) {eventAffinityScoreDOS.forEach((eventAffinityScoreDO) -> {//更新EventAffinityScoreDO表数据updateOrAddAffinity(tenantId,eventAffinityScoreDO.getChatLabsId(),eventAffinityScoreDO.getEconomyId(),eventAffinityScoreDO.getAttributeValue(),eventSubject,eventAffinityScoreDO.getAttributeName());});}

单个线程一个个遍历去更新表数据太慢了,我想把2000的数据分成多份,每份200条,可以分成10份。每份用一个线程去跑。这样跑2000的时间就大大缩短。大概等于跑200个数据的时间。
这里想到使用CountDownLatch

2.知识点CountDownLatch

CountDownLatch 是 Java 中的一个并发工具类,用于在多线程环境中控制线程的执行顺序。它允许一个或多个线程等待其他线程完成操作后再继续执行。
CountDownLatch 的构造方法接受一个整数作为参数,表示需要等待的线程数量。当一个线程完成了自己的任务后,可以调用 countDown() 方法来将计数器减1。当计数器的值变为0时,所有等待的线程都会被释放,可以继续执行。

3.解决问题

我们使用Lists.partition,把2000的集合拆分成每份200的小份,共10分。
CountDownLatch countDownLatch = new CountDownLatch(partition.size())设置CountDownLatch需要等待的线程数为拆分后的份数partition.size(),也就是10份
countDownLatch.countDown(); 每跑完一份计数器减一
countDownLatch.await();计数器减完主程序开始执行,继续循环后面的2000份

 private void eventSubjectHandle(String tenantId, String eventSubject)throws InterruptedException {// 查询eventAffinityScoreDO表,更新时间小于今天的(今天更新过的不更新)final Integer pageSize = 2000;PageResult<EventAffinityScoreDO> groupPag =eventAffinityScoreDbService.findByTenantIdAndTimePage(tenantId, eventSubject, 1,pageSize);Integer pages = groupPag.getPages();Integer pageNum = groupPag.getPageNum();while (pages >= pageNum) {if (pageNum > 1) {groupPag =eventAffinityScoreDbService.findByTenantIdAndTimePage(tenantId, eventSubject, 1, pageSize);}List<EventAffinityScoreDO> list = groupPag.getList();//Lists.partition把list进行拆分,没份200个List<List<EventAffinityScoreDO>> partition = Lists.partition(list, 200);//设置需要等待的线程数量,就是我们的集合大小CountDownLatch countDownLatch = new CountDownLatch(partition.size());for (List<EventAffinityScoreDO> eventAffinityScoreDOS : partition) {eventSubjectExecutorPool.execute(() -> {try {forEventAffinityScore(tenantId, eventSubject, eventAffinityScoreDOS);} catch (Exception e) {log.info("AutoAffinityJob updateAffinityByEventSubject error tenantId:{},eventSubject:{}",tenantId,eventSubject,e);}//每处理完200份计数器减一countDownLatch.countDown();});}//计数器减完主程序开始执行,继续循环后面的2000份countDownLatch.await();if (list.size() < pageSize) {break;}pageNum++;}}private void forEventAffinityScore(String tenantId, String eventSubject, List<EventAffinityScoreDO> eventAffinityScoreDOS) {eventAffinityScoreDOS.forEach((eventAffinityScoreDO) -> {// 根据生态中事件属性属性值更新or新增影响到的内容亲和力updateOrAddAffinity(tenantId,eventAffinityScoreDO.getChatLabsId(),eventAffinityScoreDO.getEconomyId(),eventAffinityScoreDO.getAttributeValue(),eventSubject,eventAffinityScoreDO.getAttributeName());});}

这里需要注意的是如果线程池设置的太小,会导致触发拒绝策略。如果触发了拒绝策略countDownLatch.countDown()就不会执行了。就会导致countDownLatch.await()一直等待。所以这里我把线程池的队列设置的很大Integer.MAX_VALUE,这样不会触发拒绝策略。因为我们最多就10个线程,也不会导致出现OOM

@Configuration
@Slf4j
public class CalculateAffinityThreadPool {@Bean(name = "eventSubjectExecutorPool")public ExecutorService eventSubjectExecutorPool() {int poolSize = ThreadExecutorUtils.getNormalCoreSize();return ThreadExecutorUtils.createNormalThreadPool(poolSize,poolSize,0L,TimeUnit.MILLISECONDS,Integer.MAX_VALUE,"eventSubject-pool",false);}}

经过测试跑30万的数据只需要20分钟了。

相关文章:

性能优化实战使用CountDownLatch

1.分析问题 原程序是分页查询EventAffinityScoreDO表的数据&#xff0c;每次获取2000条在一个个遍历去更新EventAffinityScoreDO表的数据。但是这样耗时比较慢&#xff0c;测试过30万的数据需要2小时 private void eventSubjectHandle(String tenantId, String eventSubject) …...

基于视频技术与AI检测算法的体育场馆远程视频智能化监控方案

一、方案背景 近年来&#xff0c;随着居民体育运动意识的增强&#xff0c;体育场馆成为居民体育锻炼的重要场所。但使用场馆内的器材时&#xff0c;可能发生受伤意外&#xff0c;甚至牵扯责任赔偿纠纷问题。同时&#xff0c;物品丢失、人力巡逻成本问题突出&#xff0c;体育场…...

leetcodetop100(29) K 个一组翻转链表

K 个一组翻转链表 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个正整数&#xff0c;它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍&#xff0c;那么请将最后剩余的节点保持原有顺序。 你不能只是单纯的改…...

最新影视视频微信小程序源码-带支付和采集功能/微信小程序影视源码PHP(更新)

源码简介&#xff1a; 这个影视视频微信小程序源码&#xff0c;新更新的&#xff0c;它还带支付和采集功能&#xff0c;作为微信小程序影视源码&#xff0c;它可以为用户 提供丰富的影视资源&#xff0c;包括电影、电视剧、综艺节目等。 这个小程序影视源码&#xff0c;还带有…...

C++:vector 定义,用法,作用,注意点

C 中的 vector 是标准模板库&#xff08;STL&#xff09;提供的一种动态数组容器&#xff0c;它提供了一组强大的方法来管理和操作可变大小的数组。以下是关于 vector 的定义、用法、作用以及一些注意点&#xff1a; 定义&#xff1a; 要使用 vector&#xff0c;首先需要包含 …...

Firecamp2.7.1exe安装与工具调试向后端发送SocketIO请求

背景&#xff1a; 笔者在python使用socket-io包时需要一个测试工具&#xff0c;选择了firecamp这个测试工具来发送请求。 参考视频与exe资源包&#xff1a; Firecamp2.7.1exe安装包以及基本使用说明文档&#xff08;以SocketIO为例&#xff09;.zip资源-CSDN文库 15_send方法…...

MySQL到TiDB:Hive Metastore横向扩展之路

作者&#xff1a;vivo 互联网大数据团队 - Wang Zhiwen 本文介绍了vivo在大数据元数据服务横向扩展道路上的探索历程&#xff0c;由实际面临的问题出发&#xff0c;对当前主流的横向扩展方案进行了调研及对比测试&#xff0c;通过多方面对比数据择优选择TiDB方案。其次分享了整…...

算法通关村-----寻找祖先问题

最近公共祖先 问题描述 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一…...

Sentinel结合Nacos实现配置持久化(全面)

1、前言 我们在进行分布式系统的开发中&#xff0c;无论是在开发环境还是发布环境&#xff0c;配置一定不能是内存形式的&#xff0c;因为系统可能会在中途宕机或者重启&#xff0c;所以如果放在内存中&#xff0c;那么配置在服务停到就是就会消失&#xff0c;那么此时就需要重…...

Verilog中什么是断言?

断言就是在我们的程序中插入一句代码&#xff0c;这句代码只有仿真的时候才会生效&#xff0c;这段代码的作用是帮助我们判断某个条件是否满足&#xff08;例如某个数据是否超出了范围&#xff09;&#xff0c;如果条件不满足&#xff08;数据超出了范围&#xff09;&#xff0…...

Oracle分区的使用详解:创建、修改和删除分区,处理分区已满或不存在的插入数据,以及分区历史数据与近期数据的操作指南

一、前言 什么是表分区: Oracle的分区是一种将表或索引数据分割为更小、更易管理的部分的技术。它可以提高查询性能、简化维护操作,并提供更好的数据组织和管理。 表分区和表空间的区别和联系: 在Oracle数据库中,表空间(Tablespace)是用于存储表、索引和其他数据库对…...

SLAM从入门到精通(amcl定位使用)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 学习slam&#xff0c;一般就是所谓的边定位、边制图的知识。然而在实际生产过程中&#xff0c;比如扫地机器人、agv、巡检机器人、农业机器人&…...

【C/C++】C/C++面试八股

C/C面试八股 C和C语言的区别简单介绍一下三大特性多态的实现原理虚函数的构成原理虚函数的调用原理虚表指针在什么地方进行初始化的&#xff1f;构造函数为什么不能是虚函数虚函数和纯虚函数的区别抽象类类对象的对象模型内存对齐是什么&#xff1f;为什么要内存对齐static关键…...

Scala第八章节

Scala第八章节 scala总目录 章节目标 能够使用trait独立完成适配器, 模板方法, 职责链设计模式能够独立叙述trait的构造机制能够了解trait继承class的写法能够独立完成程序员案例 1. 特质入门 1.1 概述 有些时候, 我们会遇到一些特定的需求, 即: 在不影响当前继承体系的情…...

k8s-实战——kubeadm二进制编译

文章目录 源码编译获取源码修改证书有效期修改 CA 有效期为 100 年(默认为 10 年)修改证书有效期为 100 年(默认为 1 年)CentOS7.9环境准备centos脚本安装执行脚本脚本内容手动安装验证编译查看编译后的版本信息参考链接脚本修改源码编译 源码编译kubeadm文件、修改证书的默…...

vite 和 webpack 的区别

1. 构建原理&#xff1a; Webpack 是一个静态模块打包器&#xff0c;通过对项目中的JavaScript、css、Image 等文件进行分析&#xff0c;生成对应的静态资源&#xff0c;并且通过一些插件和加载器来实现各种功能。 Vite 是一种基于浏览器元素 ES 模块解析构建工具&#xff0c…...

传统遗产与技术相遇,古彝文的数字化与保护

古彝文是中国彝族的传统文字&#xff0c;具有悠久的历史和文化价值。然而&#xff0c;由于古彝文的形状复杂且没有标准化的字符集&#xff0c;对其进行文字识别一直是一项具有挑战性的任务。本文介绍了古彝文合合信息的文字识别技术&#xff0c;旨在提高古彝文的自动识别准确性…...

多维时序 | MATLAB实现WOA-CNN-GRU-Attention多变量时间序列预测(SE注意力机制)

多维时序 | MATLAB实现WOA-CNN-GRU-Attention多变量时间序列预测&#xff08;SE注意力机制&#xff09; 目录 多维时序 | MATLAB实现WOA-CNN-GRU-Attention多变量时间序列预测&#xff08;SE注意力机制&#xff09;预测效果基本描述模型描述程序设计参考资料 预测效果 基本描述…...

1042 字符统计

description 请编写程序&#xff0c;找出一段给定文字中出现最频繁的那个英文字母。 输入格式&#xff1a; 输入在一行中给出一个长度不超过 1000 的字符串。字符串由 ASCII 码表中任意可见字符及空格组成&#xff0c;至少包含 1 个英文字母&#xff0c;以回车结束&#xff…...

3 OpenCV两张图片实现稀疏点云的生成

前文&#xff1a; 1 基于SIFT图像特征识别的匹配方法比较与实现 2 OpenCV实现的F矩阵RANSAC原理与实践 1 E矩阵 1.1 由F到E E K T ∗ F ∗ K E K^T * F * K EKT∗F∗K E 矩阵可以直接通过之前算好的 F 矩阵与相机内参 K 矩阵获得 Mat E K.t() * F * K;相机内参获得的方式…...

别再死记硬背了!用‘快递寄送’和‘跨国通话’的比喻,5分钟搞懂OSI七层模型与TCP/IP五层模型

快递与越洋电话&#xff1a;用生活场景拆解网络分层模型 想象一下&#xff0c;你网购的商品从深圳工厂到北京家门口&#xff0c;要经过打包、装车、跨省运输、本地配送多个环节——这和网络数据传输的层层封装如出一辙。而当你给海外亲友视频通话时&#xff0c;双方手机自动协商…...

8086汇编实战:用ZF、PF、SF标志位调试你的第一个程序(附调试截图)

8086汇编实战&#xff1a;用ZF、PF、SF标志位调试你的第一个程序&#xff08;附调试截图&#xff09; 刚接触汇编语言时&#xff0c;很多人会被那些神秘的标志位搞得一头雾水。记得我第一次在调试器里看到ZF、PF、SF这些缩写时&#xff0c;完全不明白它们有什么用——直到我在实…...

华为eNSP实战:三层交换机互连配置全流程(附常见错误排查)

华为eNSP实战&#xff1a;三层交换机互连配置全流程&#xff08;附常见错误排查&#xff09; 在企业网络架构中&#xff0c;三层交换机扮演着至关重要的角色&#xff0c;它不仅能实现二层交换功能&#xff0c;还能进行三层路由转发。华为eNSP作为一款优秀的网络仿真平台&#x…...

终极Illusion游戏Mod管理指南:用KKManager告别插件混乱

终极Illusion游戏Mod管理指南&#xff1a;用KKManager告别插件混乱 【免费下载链接】KKManager Mod, plugin and card manager for games by Illusion that use BepInEx 项目地址: https://gitcode.com/gh_mirrors/kk/KKManager 你是否曾经因为Mod冲突导致游戏崩溃而烦恼…...

Python邮件自动化实战:基于imaplib和email库的高效邮件处理方案

1. Python邮件自动化处理的核心价值 每天早晨打开邮箱&#xff0c;看到堆积如山的未读邮件时&#xff0c;你是否感到头皮发麻&#xff1f;作为曾经每天要处理200封邮件的市场分析师&#xff0c;我完全理解这种痛苦。直到发现Python的imaplib和email这对黄金组合&#xff0c;我的…...

Qwen3-0.6B-FP8快速上手:Anaconda环境下的Python开发配置

Qwen3-0.6B-FP8快速上手&#xff1a;Anaconda环境下的Python开发配置 想试试最新的轻量级大模型Qwen3-0.6B-FP8&#xff0c;但被Python环境搞得头大&#xff1f;别担心&#xff0c;今天咱们就来手把手搞定它。很多朋友在第一步——环境配置上就卡住了&#xff0c;要么是包版本…...

FreeRTOS内存管理实战:如何在Xilinx Zynq上正确配置堆大小避免Malloc失败

FreeRTOS内存管理实战&#xff1a;Xilinx Zynq平台堆配置与优化指南 在嵌入式系统开发中&#xff0c;内存管理往往是决定系统稳定性的关键因素之一。当你在Xilinx Zynq平台上使用FreeRTOS时&#xff0c;突然遇到vApplicationMallocFailedHook()被调用的错误提示&#xff0c;这就…...

清华大学学位论文LaTeX模板:thuthesis完整使用指南

清华大学学位论文LaTeX模板&#xff1a;thuthesis完整使用指南 【免费下载链接】thuthesis LaTeX Thesis Template for Tsinghua University 项目地址: https://gitcode.com/gh_mirrors/th/thuthesis 清华大学thuthesis LaTeX模板是专为清华学子设计的学位论文写作工具&…...

Windows 10/11 上 Docker 部署 Milvus 与 Attu 图形化界面全攻略

1. Windows 系统准备与 Docker 安装 在 Windows 10/11 上部署 Milvus 之前&#xff0c;需要确保系统环境满足基本要求。我实测发现&#xff0c;Windows 家庭版默认不支持 Hyper-V&#xff0c;需要先升级到专业版或企业版。检查系统版本的方法很简单&#xff1a;右键点击"此…...

AI写专著必备:优质工具大盘点,全方位提升专著撰写效率

撰写学术专著时&#xff0c;研究者需要在“内容的深度”和“覆盖的广度”之间找到一个恰当的平衡&#xff0c;而这正是许多人面临的主要难题。从深度出发&#xff0c;专著的核心论点需要具备足够的学术分量&#xff0c;不仅要清楚解答“是什么”&#xff0c;还应该深入探讨“为…...