CountDownLatch阻塞后countDown未执行会如何?
背景
某项目封装了 Kafka 消费者 API,根据传递的消费者线程数,创建 N 个消费者线程同时消费对应 topic 的数据,并在线程启动后收集到全局列表中,方便在程序调用 stop 流程时逐个停止。
主控类在创建 Kafka 消费线程时使用了 CountDownLatch ,将启动的线程收集到全局列表,并阻塞等待所有线程初始化完成;消费者线程指定 Kafka 订阅方法后对计数器减一,然后轮询消费 Kafka 的数据。
近日因某场景下不想消费某类 topic 数据而将 topic 设置为空,预想其他几类的 topic 数据应该正常消费,结果发现第一个 topic 设置为空后,其他几类消费线程都没有正常启动。
封装逻辑
程序封装了一个 KafkaConsumerThread 类,根据配置的线程数启动 N 个线程消费目标 topic 数据,基本代码如下:

用 CountDownLatch 控制消费者线程的初始化,本意是在 run 方法执行的时候就对计数器减一,标识本消费线程初始化完成的。
- 根据线程数创建
CountDownLatch计数器。 - 订阅 Kafka topic。
- 计数器减一。
- 记录启动的线程对象。
- 主程序阻塞等待消费线程 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 之后调用,因为该语句会异常。
到底应该在哪里对计数器减一才能保证即使异常,也能正常减一呢?有两个方法:
- 简化处理,在线程的 run 方法第一行调用。
- 稍微复杂一点,添加一个开关,在 countDown 后面设置为 true,然后再 finally 里面判断,如果这个开关的代码没有走到,说明后面异常了,就在对计数器再补充减一:

其实这个问题产生的根源是没有对 topic 进行判空,如果源头控制了,就不会出现这种异常了。
PS:真心再推荐一下 utools 工具,整理本文时堆栈信息是从七天前的剪切板里面找出来的:

对我这种一天不知道复制粘贴多少次的人来说,这个工具真的很好用啊!
相关文章:
CountDownLatch阻塞后countDown未执行会如何?
背景 某项目封装了 Kafka 消费者 API,根据传递的消费者线程数,创建 N 个消费者线程同时消费对应 topic 的数据,并在线程启动后收集到全局列表中,方便在程序调用 stop 流程时逐个停止。 主控类在创建 Kafka 消费线程时使用了 Cou…...
k8s,operator
相对更加灵活和编程友好的管理“有状态应用”的解决方案,它就是:Operator 会议一下有状态应用: 比如数据库集群,数据挂载需要有顺序维护拓扑关系的应用 使用statefulSet这个对象来描述。 CRD又是什么? Operator的工作…...
使用 pyperclip 进行跨平台剪贴板操作
简介:pyperclip 是一个轻量级的 Python 库,支持在不同操作系统(Windows、macOS、Linux)中进行剪贴板的复制和粘贴。这个库的设计简单易用,非常适合需要频繁进行文本复制粘贴操作的场景。 历史攻略: 使用f…...
20 设计模式之职责链模式(问题处理案例)
一、什么是职责链模式 职责链模式是一种行为型设计模式,它允许将请求沿着处理者的链进行传递,直到有一个处理者能够处理它为止。换句话说,它将请求的发送者和接收者解耦,使得多个对象都有机会处理这个请求,从而避免了将…...
SpringBoot3集成MybatisPlus3和knife4j(swagger3兼容增强版)
针对Swagger2规范和OpenAPI3规范的说明: 在Spring Boot框架中,Knife4j对于服务端将Spring的开放接口解析成Swagger2或者OpenAPI3规范的框架,也是依赖的第三方框架组件。说明如下: Swagger2规范:依赖Springfox项目,该项目目前几乎处于停更状态,但很多老项目依然使用的是该…...
【MIT-OS6.S081作业1.3】Lab1-utilities primes
本文记录MIT-OS6.S081 Lab1 utilities 的primes函数的实现过程 文章目录 1. 作业要求primes (moderate)/(hard) 2. 实现过程2.1 代码实现 1. 作业要求 primes (moderate)/(hard) Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, in…...
游戏引擎学习第35天
开场介绍 今天的任务是继续改进一个虚拟的瓦片地图系统,使其适合处理更大的世界。我们希望这个系统能管理大范围的游戏世界,其中包含按需存储的小区域。昨天,我们介绍了“内存区域”的概念,用于管理持久性存储。我们计划今天继续…...
learn-(Uni-app)输入框u-search父子组件与input输入框(防抖与搜索触发)
1.父子组件u-search (1)父组件 <!-- 父组件 --> <template> <div><searchBar change"change" search"search"></searchBar> </div> </template> <script> // 子组件搜索 import…...
设置IMX6ULL开发板的网卡IP的两种方法(临时生效和永久有效两种方法)
设置开发板网卡的IP,有两种方法。 方法一:临时生效 第一种方式是临时设置,只有本次有效,重启后又要重新设,命令为: ifconfig eth0 192.168.5.9设置成功后可以使用ifconfig命令来查看已设置的 IP 地址。 …...
流量转发利器之Burpsuite概述(1)
目录 一、Burpsuite Burp Suite Spider 的主要特点: 在 Burp Suite 中使用 Spider: Spider 的用例: 限制: 声明:学习视频来自b站up主 泷羽sec,如涉及侵权马上删除文章 声明:本文主要用作技…...
Transformer入门(6)Transformer编码器的前馈网络、加法和归一化模块
文章目录 7.前馈网络8.加法和归一化组件9.组合所有编码器组件构成完整编码器 7.前馈网络 编码器块中的前馈网络子层如下图所示: 图1.32 – 编码器块 前馈网络由两个带有ReLU激活函数的全连接层组成。全连接层(Fully Connected Layer)有时也…...
element-plus中的resetFields()方法
resetFields()确实是Element Plus中的方法,该方法主要用于重置表单,将其值重置为初始值,并移除校验结果。以下是对该方法的详细解释: 一、resetFields方法的作用 在Vue3结合Element Plus开发时࿰…...
【过滤器】.NET开源 ORM 框架 SqlSugar 系列
目录 0、 过滤器介绍 1、表过滤器 (推荐) 1.1 手动添加过滤器 1.2 禁用、清空、备份和还原 1.3 联表查询设置 1.4 动态添加 2、修改和删除用过滤器 2.1 局部设置 2.2 全局设置 (5.1.4.62) 3、子查询用过滤器 4、联表过滤…...
Jmeter Address already in use: connect 解决
做压测接口时,并发一段时间后,会报java.net.BindException: Address already in use: connect 原因: windows提供给TCP/IP链接的端口为 1024-5000,并且要四分钟来循环回收它们,就导致在短时间内跑大量的请求时将端口占…...
C#常见错误—空对象错误
System.NullReferenceException:未将对象引用设置到对象的实例 在C#编程中,System.NullReferenceException是一个常见的运行时异常,其错误信息“未将对象引用设置到对象的实例”意味着代码试图访问一个未被初始化或已被设置为null的对象的成…...
Leetcode数学部分笔记
Leetcode数学部分笔记 1. 回文数2. 加一3. 阶乘后的零4. x 的平方根5. Pow(x, n) 1. 回文数 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数 是指正序(从左向右)和倒序&…...
微信小程序web-view 嵌套h5界面 实现文件预览效果
实现方法:(这里我是在小程序里面单独加了一个页面用来下载预览文件) 安装 使用方法请参考文档 npm 安装 npm install weixin-js-sdk import wx from weixin-js-sdk预览 h5界面代码 <u-button click"onclick" type"primary" :loading"…...
【汽车】-- 燃油发动机3缸和4缸
3缸和4缸燃油发动机是小轿车常见的发动机配置。以下从结构特点、性能、经济性等方面对两者进行对比,并分析优缺点及使用注意事项: 1. 结构与运行原理 3缸发动机 特点:少一个气缸,内部零部件更少,整体结构更紧凑。优点…...
轻量级的 HTML 模板引擎
Mustache 简介:Mustache 是一个非常简单的逻辑少的模板引擎,支持 HTML 文件中的占位符替换。它不会执行复杂的逻辑,只支持简单的变量替换。 安装: npm install mustache示例: const Mustache require(mustache);c…...
Mysql | 尚硅谷 | 第02章_MySQL环境搭建
Mysql笔记:第02章_MySQL环境搭建 说明:本内容整理自尚硅谷B站MySQL视频>>尚硅谷B站MySQL视频 文章目录 Mysql笔记:第02章_MySQL环境搭建第02章_MySQL环境搭建 1. MySQL的卸载步骤1:停止MySQL服务步骤2:[软件](h…...
css实现圆环展示百分比,根据值动态展示所占比例
代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...
【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)
🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建
华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...
2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
