并发线程无响应问题排查:ExecutorService配置是否有误?
ExecutorService配置是否有误?
你使用的Executors.newFixedThreadPool(10)本身没有配置错误,固定大小线程池适用于这种批量并发任务场景。但线程停滞的问题大概率出在任务逻辑、依赖资源或初始化时机上,而非线程池本身。
核心问题推测
超大分页查询阻塞
每页查询50万条数据属于极端不合理的分页参数:数据库需要扫描并返回巨量数据,不仅会占用大量数据库资源,还可能导致JVM内存压力陡增,线程长时间卡在数据库IO阶段。数据库连接池耗尽
10个线程同时发起查询,若数据库连接池的最大连接数小于10,或查询耗时过长占用连接不释放,会导致后续线程等待获取连接,整体陷入阻塞。Spring初始化时机问题
@PostConstruct执行时,Spring容器可能尚未完全初始化StudentRepo或KafkaProducer,异步线程调用未就绪的Bean方法会导致卡住。未处理的静默异常
executor.submit()提交的任务若抛出异常,不会主动打印日志,线程会静默终止,看起来像是“停滞”。比如数据库查询超时、权限问题等。数据库锁或性能瓶颈
查询的表可能存在锁竞争,或数据库本身性能不足,导致查询请求长时间处于等待状态。
生产环境排查步骤
检查应用日志
确认log.info("result: {}",students )是否有输出:- 无输出:说明线程卡在
findStudentsWithPagination方法,需查看数据库的SQL执行日志,排查查询是否超时、是否存在锁等待。 - 有输出但未执行Kafka发送:检查KafkaProducer是否初始化完成,或发送方法是否抛出静默异常。
- 无输出:说明线程卡在
分析数据库状态
用数据库自带工具查看进程列表(如MySQL的show processlist),确认是否有长时间运行的查询进程,是否存在锁等待、连接耗尽的情况。抓取JVM线程栈
使用jstack <进程ID>命令导出线程栈,查看这10个线程的状态:- 若处于
WAITING状态:大概率在等待数据库连接或锁资源。 - 若处于
RUNNABLE状态:可能卡在数据库IO或大数据量内存处理阶段。
- 若处于
监控连接池指标
查看数据库连接池的监控数据(如HikariCP的连接数、等待队列长度),确认是否存在连接耗尽的情况。调整分页参数测试
临时将每页数据量从50万降至合理值(如1000或5000),验证线程是否能正常执行,排除超大查询量导致的阻塞。修正任务异常处理
在异步任务中添加try-catch捕获所有异常,避免静默失败:executor.submit(()->{ try { // 注意:pageNo变量未定义,需替换为合理的分页参数,比如用循环变量a作为页码 List<StudentEntity> students = studRepo.findStudentsWithPagination(PageRequest.of(a, 1000)); log.info("Thread {} fetched {} students", a, students.size()); kafkaProducer.send(students); } catch (Exception e) { log.error("Thread {} execution failed", a, e); } });调整Spring初始化时机
避免在@PostConstruct中启动异步线程,改用ApplicationReadyEvent监听,确保所有Bean完全初始化后再执行任务:@EventListener(ApplicationReadyEvent.class) public void initAfterReady(){ // 线程池初始化和任务提交逻辑 }
内容的提问来源于stack exchange,提问作者Arun Sai

