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

多线程下任务状态异常的问题解决

多线程下任务状态异常的问题解决

  • 场景描述
  • 问题描述
  • 问题分析
  • 相关知识总结
    • 事务范围
    • 循环中的更新
    • 锁和并发
    • 超时和异常处理
  • 问题解决

场景描述

在一个线程中将一批任务通过循环依次添加到LinkedBlockingQueue中,并将任务状态改为待执行。后台使用mysql数据库。然后另外有一个线程从这个queue中阻塞取出任务,并执行,这时将任务状态修改为执行中。

@TransactionalpublicvoidtaskBatchSchedule(List<Integer>ids){for(Integerid:ids){Tasktask=getTask(id);queue.put(task);updateTaskWait(task);}}

问题描述

在这个场景下,任务状态的变更有时候正常,有时出现问题:第一个任务状态一直已经执行但状态还为待执行,执行结束后任务状态修改为执行结束。接着第二个任务正常显示任务状态。

问题分析

这里有生产和消费两个线程,当生产线程循环去添加任务并连接数据库更新任务状态。当生产端还没结束,事务还未提交(一个方法视为一个事务)。此时,消费端已经取出任务队列中第一个任务去执行。当它去更改任务状态时,由于生产线程的事务还未提交。消费线程等待超时后便继续向后执行,任务状态修改失败。

在我这个场景中,第一个任务执行的时候最容易出现该问题,因为此时生产和消费线程同时竞争数据库资源,第二,或者后面的任务在执行的时候,生产线程已经结束,就不太会出现这个问题。

相关知识总结

事务范围

  • 当方法上标注了@Transactional注解时,整个方法体内的所有数据库操作都会在一个统一的事务范围内进行。
  • 这意味着事务会在方法执行开始时开启,并在方法正常完成时提交,或者在方法中抛出未被捕获的异常时回滚。

循环中的更新

  • 如果在一个循环中更新多条记录,这些更新操作都会在同一事务中进行。
  • 即使循环中有多个数据库操作,也只有在循环结束后整个方法执行完成时,事务才会提交。

锁和并发

  • 在循环中更新数据时,如果其他线程尝试同时更新相同的记录,那么这些线程将等待锁释放,或者因为锁等待超时而失败。
  • MySQL默认使用行级锁,在InnoDB存储引擎中,当一个事务正在更新一行数据时,它会对那行数据加上排他锁(X锁),阻止其他事务同时更新该行数据。

超时和异常处理

  • 通过@Transactional(timeout = seconds)来设置事务的最大执行时间。如果事务在此时间内没有完成,Spring会自动回滚事务并抛出异常。
  • 如果事务因为长时间等待锁而超时,MySQL会抛出LockWaitTimeoutException,Spring会将其转换为TransactionSystemException异常。捕获并处理TransactionSystemException异常,以确保应用程序能够优雅地处理这种情形。调整MySQL的innodb_lock_wait_timeout系统变量来配置数据库级别的锁等待超时时间。

问题解决

问题在于两个线程资源争夺所造成,所以这里我使用了ReentrantLock来同步生产和消费线程。另外,将生产线程里,循环更新任务状态改为批量更新,特别是在数据批次较大的时候,能够显著减少数据库操作次数,减少事务持续时间。

愿你我都能在各自的领域里不断成长,勇敢追求梦想,同时也保持对世界的好奇与善意。

http://www.cnnetsun.cn/news/3453962.html

相关文章:

  • DiscordX音乐机器人开发:LavaPlayer与YTDL插件的终极集成指南
  • Rust Rosetta Code贡献指南:如何为开源项目提交你的第一个PR
  • 解密多智能体金融交易框架:如何用AI打造你的专属投资团队
  • OBS Studio滤镜系统深度解析:从源码架构到专业级画质调优实战
  • STM32N6570外部Flash烧录与FSBL引导配置指南
  • OpenEuler CreateImage 核心函数库探秘:lib 目录下的 common-functions 与 img-functions
  • uos-uwsgi-exporter深度解析:从架构设计到实战部署的完整教程
  • 终极指南:如何用Zotero Style插件打造你的专属文献阅读体验
  • 3步构建个人云影院:115网盘原码直连Kodi播放方案
  • 如何用happy-lager快速搭建企业级网站?Craft CMS模板开发终极指南
  • 卤味熟食店如何解决社区获客难题?餐宝盈小程序与GEO服务带来稳定订单,含零代码SAAS、AI编程、源码定制
  • 如何用1个免费应用看遍所有直播?Simple Live终极聚合方案
  • 完整指南:如何使用IDM激活脚本永久解决Internet Download Manager试用限制
  • 解密本地视频字幕提取:从手动转录到智能AI的进化之路
  • dnSpyEx:3大核心功能解析.NET程序调试与逆向工程的终极解决方案
  • Hermes 完整部署排障清单,解决 90% Windows 安装异常
  • SillyTavern突破指南:3大挑战与高效解决方案
  • 2026私域商城小程序平台口碑榜单:餐宝盈、BBWEYY、比文云、SaaS哥、维双云对比,含零代码SAAS、AI编程、源码定制
  • 小程序毕设项目:同城生鲜配送系统的设计与实现 基于 SpringBoot + 微信小程序的家庭生鲜采购服务小程序 (源码+文档,讲解、调试运行,定制等)
  • Go-Queryset项目实战:从零构建企业级应用的数据访问层
  • 【Springboot毕设全套源码+文档】基于SpringBoot的音乐分享与交流平台设计与实现(丰富项目+远程调试+讲解+定制)
  • Legacy-iOS-Kit:让经典苹果设备重获新生的终极工具链
  • 罗丹明类荧光染料:从分子结构到前沿应用
  • C++实现Bresenham直线光栅化算法:原理详解与代码实战
  • PCB布局设计核心原则与高频电路优化技巧
  • STM32H7 MCU驱动MIPI DSI显示接口实战指南
  • GaN Doherty功放设计:效率优化与宽带实现
  • SingGuard-4b实战应用:10个常见场景的安全检测案例
  • 如何在Windows 11家庭版免费启用远程桌面多用户连接:RDP Wrapper完整教程
  • OBS Studio转场效果终极指南:如何创建专业级场景切换动画