京东6.18大促主会场领京享红包更优惠

 找回密码
 立即注册

QQ登录

只需一步,快速开始

消费者Consumer启动后为啥程序一直挂着不退出 ?

2026-6-29 14:52| 发布者: zhaojun917| 查看: 6| 评论: 0

摘要: # 原因完整说明 解决办法 ## 一、核心根本原因(程序常驻不退出的3点) ### 1. `System.in.read()` 控制台阻塞等待(最直观原因) ```java System.in.read(); ``` 这行代码会**阻塞主线程**,等待你在控制台手动输 ...
 
# 原因完整说明 & 解决办法 ## 一、核心根本原因(程序常驻不退出的3点) ### 1. `System.in.read()` 控制台阻塞等待(最直观原因) ```java System.in.read(); ``` 这行代码会**阻塞主线程**,等待你在控制台手动输入字符、按下回车,代码才会往下执行 `testConsumerStop()` 和 `shutdown()`。 只要你不在Console窗口敲内容回车,主线程就卡在这一步,程序自然不会结束。 ### 2. RocketMQ 客户端自带**非守护常驻后台线程** 哪怕删掉 `System.in.read()`,生产者Producer、消费者Consumer启动后,内部自带大量常驻非守护线程: - Netty网络IO线程池、TCP心跳线程、定时路由刷新线程、消费拉取线程 - JVM判定:**存在非守护线程运行,进程不会主动退出** 必须手动调用 `consumer.shutdown()` / `producer.shutdown()` 关闭MQ客户端,销毁这些后台线程,进程才能正常结束。 ### 3. 当前日志证明收发完全正常 从控制台日志可以确认: 1. Producer启动成功,消息发送成功,MsgId正常生成 2. 测试Consumer正常启动,成功拉取并消费到测试消息 MQ客户端已经完整运行,常驻线程全部启动。 --- ## 二、两种解决方式 ### 方式1:手动控制台回车放行(当前代码设计本意) 1. 切换到下方Console控制台窗口 2. 随便敲一个字母,按下**回车键** 3. `System.in.read()` 读取到输入,继续执行:关闭测试消费者 → 执行全局`shutdown()`关闭所有Producer/Consumer → 所有MQ后台线程销毁,程序正常结束。 ### 方式2:临时改成自动退出(测试用) 如果不想手动输入,测试完直接自动关闭,可以把阻塞代码替换为休眠,等待消费完成后自动执行关闭: ```java testConsumerStart(); // 等待2秒,保证消息消费完毕 TimeUnit.SECONDS.sleep(2); testConsumerStop(); RocketUtil.shutdown(); ``` ## 三、补充知识点 1. **守护线程区别** MQ的IO/消费线程都是**非守护线程**,JVM必须等它们全部结束才会退出;垃圾回收、定时任务这类守护线程不会阻碍进程退出。 2. 后续正式项目 SpringBoot环境会由容器管理生命周期,项目关闭时自动触发我们写的JVM关闭钩子 `shutdownHook`,优雅关闭MQ客户端;只有本地main测试程序,需要手动控制启停时机。 3. 额外验证 执行完`shutdown()`后观察日志,会打印`Producer正常关闭`、`Consumer关闭`日志,代表常驻线程回收完毕,程序随即终止。

QQ|手机版|小黑屋|梦想之都-俊月星空 ( 粤ICP备18056059号 )|网站地图

GMT+8, 2026-6-30 01:54 , Processed in 0.089178 second(s), 18 queries .

Powered by Mxzdjyxk! X3.5

© 2001-2026 Discuz! Team.

返回顶部