CountDownLatch阻塞后countDown未执行会如何?

背景

某项目封装了 Kafka 消费者 API,根据传递的消费者线程数,创建 N 个消费者线程同时消费对应 topic 的数据,并在线程启动后收集到全局列表中,方便在程序调用 stop 流程时逐个停止。

主控类在创建 Kafka 消费线程时使用了 CountDownLatch ,将启动的线程收集到全局列表,并阻塞等待所有线程初始化完成;消费者线程指定 Kafka 订阅方法后对计数器减一,然后轮询消费 Kafka 的数据。

近日因某场景下不想消费某类 topic 数据而将 topic 设置为空,预想其他几类的 topic 数据应该正常消费,结果发现第一个 topic 设置为空后,其他几类消费线程都没有正常启动。

封装逻辑

程序封装了一个 KafkaConsumerThread 类,根据配置的线程数启动 N 个线程消费目标 topic 数据,基本代码如下:
在这里插入图片描述
用 CountDownLatch 控制消费者线程的初始化,本意是在 run 方法执行的时候就对计数器减一,标识本消费线程初始化完成的。

  1. 根据线程数创建 CountDownLatch 计数器。
  2. 订阅 Kafka topic。
  3. 计数器减一。
  4. 记录启动的线程对象。
  5. 主程序阻塞等待消费线程 run 方法执行到计数器减一。

问题排查

有一个 topic 设置为空后,对应的消费者线程启动报异常了:

java.lang.IllegalArgumentException: 
Topic collection to subscribe to 
cannot contain null or empty topic

一个消费异常,但其他消费者没有启动,为什么呢?理论上它们并不相干才对。

打印程序堆栈信息,发现程序阻塞了:
在这里插入图片描述

封装的 Kafka API 是顺次启动几类 topic 消费线程的,因为启动第一个 topic 消费线程时,因 topic 设置为空,consumer.subscribe(config.getTopics()) 这句代码异常了,其后面的 countDown 未执行而引发阻塞

第一个 topic 消费启动异常后,程序因调用了 countDownLatch.await() 而阻塞了,因此后面代码就不执行了,继而程序呈现异常状态。

基础巩固

CountDownLatch 是 JUC 包同步工具类,用于协调多个线程。它允许一个或多个线程等待,直到其他线程中执行的一组操作完成。CountDownLatch 通过一个计数器来实现,该计数器由线程递减,计数器值到达零后,所有调用过 await 方法的线程将解除阻塞状态。

  • 创建:new CountDownLatch 对象时,指定计数器的初始值。
  • 阻塞:一个或多个线程调用 await 方法,进入阻塞等待状态,直到计数器的值变为零。
  • 倒计数:其他线程在完成各自任务后调用 countDown 方法,将计数器的值减一。当计数器的值减到零时,所有在 await 上等待的线程会被唤醒,继续执行。

启示录

同步锁使用不当容易引发死锁问题,阿里开发者规范在 countDown() 方法处有一个提示:
在这里插入图片描述
这个提示也不准确,因为这个是一个 Kafka 消费线程,它以线程中断状态为标识,循环从 Kafka 中 poll 数据处理的,所以不能在 finally 中调用。但是也不能在 subscribe 之后调用,因为该语句会异常。

到底应该在哪里对计数器减一才能保证即使异常,也能正常减一呢?有两个方法:

  1. 简化处理,在线程的 run 方法第一行调用。
  2. 稍微复杂一点,添加一个开关,在 countDown 后面设置为 true,然后再 finally 里面判断,如果这个开关的代码没有走到,说明后面异常了,就在对计数器再补充减一:在这里插入图片描述
    其实这个问题产生的根源是没有对 topic 进行判空,如果源头控制了,就不会出现这种异常了。

PS:真心再推荐一下 utools 工具,整理本文时堆栈信息是从七天前的剪切板里面找出来的:
在这里插入图片描述
对我这种一天不知道复制粘贴多少次的人来说,这个工具真的很好用啊!

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

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

相关文章

NLP与LLM的工程化实践与学习思考 - 说说知识图谱

NLP与LLM的工程化实践与学习思考[24年半年工作总结] - 说说知识图谱 0 真的就是先说说1 为什么知识图谱什么是知识图谱?基于图的数据结构?基于数据结构的图?知识图谱的技术要点两个技术维度:知识、图七个技术要点:表示…

【CVE-2024-5660】ARM CPU漏洞:硬件页面聚合(HPA)安全通告

安全之安全(security)博客目录导读 目录 一、概述 二、修改历史 三、什么是硬件页面聚合? 四、修复解决 一、概述 在一些基于arm的cpu中发现了一个问题,该问题可能允许修改的、不受信任的客户机操作系统(guest OS)危及某些H…

项目中使用AntV L7地图(五)添加飞线

项目中使用AntV L7地图,添加 飞线 文档地址:https://l7.antv.antgroup.com/zh/examples/line/animate/#trip_animate 一、初始化地图 使用的地图文件为四川地图JSON,下载地址:https://datav.aliyun.com/portal/school/atlas/area_selector#&…

《九重紫》逐集分析鉴赏—序言、概览、框架分析

主标题:《九重紫》一起追剧吧副标题:《九重紫》逐集分析鉴赏—序言、概览、框架分析《永夜星河》后,以为要浅尝剧荒,一部《九重紫》突出重围。 看了宣传片感觉不是很差,看了部分剪辑感觉还可以,看了一两集感…

生成式AI概览与详解

1. 生成式AI概览:什么是大模型,大模型应用场景(文生文,多模态) 生成式AI(Generative AI)是指通过机器学习模型生成新的数据或内容的人工智能技术。生成式AI可以生成文本、图像、音频、视频等多种…

0001.简易酒店管理系统后台

一.系统架构 springmvcjsplayuimysql 二.功能特性 简单易学习,虽然版本比较老但是部署方便,tomcat环境即可启用;代码简洁,前后端代码提供可统一学习;祝愿您能成尽快为一位合格的程序员,愿世界没有BUG; …

STM32软件IIC驱动TCA9548A多路测量AHT10

STM32软件IIC驱动TCA9548多路测量AHT10 TCA9548AAHT10代码逻辑代码展示现象总结 TCA9548A TCA9548A 有八个可通过 I2C 总线控制的双向转换开关,SCL/SDA 上行对扩展到八个下行对,或者通道,适用于系统中存在I2C目标地址冲突的情况。8路双向转换…

信奥赛CSP-J复赛集训(dfs专题)(15):洛谷P8838:[传智杯 #3 决赛] 面试

信奥赛CSP-J复赛集训(dfs专题-刷题题单及题解)(15):洛谷P8838:[传智杯 #3 决赛] 面试 题目背景 disangan233 和 disangan333 去面试了,面试官给了一个问题,热心的你能帮帮他们吗? 题目描述 现在有 n n n 个服务器,服务器

ARM学习(36)静态扫描规则学习以及工具使用

笔者来学习了解一下静态扫描以及其规则,并且亲身是实践一下对arm 架构的代码进行扫描。 1、静态扫描认识 静态扫描:对代码源文件按照一定的规则进行扫描,来发现一些潜在的问题或者风险,因为不涉及代码运行,所以其一般…

Python机器学习笔记(五、决策树集成)

集成(ensemble)是合并多个机器学习模型来构建更强大模型的方法。这里主要学习两种集成模型:一是随机森林(random forest);二是梯度提升决策树(gradient boosted decision tree)。 1…

为什么数据平台需要敏捷版|直播回顾

11月28日,我们邀请到StartDT合伙人、CTO地雷和StartDT资深战略咨询专家何夕,围绕“为什么数据平台需要敏捷版”这个话题,向大家汇报了DataSimba敏捷版这半年来的最新进展,并带来了详细的产品解读。 敏捷版支持StarRocks、ClickHo…

SpringBoot【九】mybatis-plus之自定义sql零基础教学!

一、前言🔥 环境说明:Windows10 Idea2021.3.2 Jdk1.8 SpringBoot 2.3.1.RELEASE mybatis-plus的基本使用,前两期基本讲的差不多,够日常使用,但是有的小伙伴可能就会抱怨了,若是遇到业务逻辑比较复杂的sq…

Android后端签到flask迁移到rust的axum的过程-签到性能和便携

本次变更了以下内容: 为了使用之前ip2sta的ip到端点名的python,dic变量,将其存入redis hashset.使用地址/api/ip2dic 手动执行之.并且定义在/station/init,这个每天初始化redis的路径下.在rust axum使用redis 连接池在test中 ip2dic,IP转端点名,转本日此端网址.在前端的人名下…

ThinkPHP知识库文档系统源码

知识库文档系统 一款基于ThinkPHP开发的知识库文档系统,可用于企业工作流程的文档管理,结构化记录沉淀高价值信息,形成完整的知识体系,能够轻松提升知识的流转和传播效率,更好地成就组织和个人。为部门、团队或项目搭…

交换排序(Swap Sort)详解

交换排序Swap Sort详解 冒泡排序冒泡算法代码实现冒泡分析 快速排序快排算法代码实现快排分析 交换类排序主要是通过两两比较待排元素的关键字,若发现与排序要求相逆,则交换之。在这类排序方法中最常见的是起泡排序(冒泡排序)和快…

091 脉冲波形的变换与产生

00 如何获得脉冲波形 01 单稳态触发器 1.分类 2.工作特点: ① 电路在没有触发信号作用时处于一种稳定状态。 ② 在外来触发信号作用下,电路由稳态翻转到暂稳态; ③ 由于电路中RC延时环节的作用,暂稳态不能长保持, 经过一段时间后&#xff0c…

高级排序算法(二):归并排序与堆排序详解

引言 在上一章中,我们探讨了高效的快速排序及其分治思想。这一次,我们将继续探索两种同样重要的排序算法:归并排序(Merge Sort) 和 堆排序(Heap Sort)。 它们与快速排序一样,都是O(…

JVM调优之如何排查CPU长时间100%的问题

对于CPU长时间100%的问题,其实有一个比较标准的排查流程,现在模拟一个垃圾回收导致的cup占用率过高的排查方法。 步骤如下: 1.先通过top命令找到消耗cpu很高的进程id 在服务器上输入top,显示如下: 通过top命令定位到…

中间件--MongoDB部署及初始化js脚本(docker部署,docker-entrypoint-initdb.d,数据迁移,自动化部署)

一、概述 MongoDB是一种常见的Nosql数据库(非关系型数据库),以文档(Document)的形式存储数据。是非关系型数据库中最像关系型数据库的一种。本篇主要介绍下部署和数据迁移。 在 MongoDB 官方镜像部署介绍中&#xff…

SkyWalking Helm Chart 4.7.0 安装、配置

https://skywalking.apache.org/events/release-apache-skywalking-kubernetes-helm-chart-4.7.0/https://github.com/apache/skywalking-helm/tree/v4.7.0https://skywalking.apache.org/zh/2020-04-19-skywalking-quick-start/简介 skywalking 是分布式系统的 APM(Applicat…