线程池存在空闲线程却将任务入队而非复用的原因排查
线程池创建
@PostConstruct public void postConstruct() { threadPool = new ThreadPoolExecutor(corePoolSize != 0 ? corePoolSize : defaultPoolSize, maxPoolSize != 0 ? maxPoolSize : defaultMaxPoolSize, defaultKeepAliveTime, TimeUnit.SECONDS, new LinkedBlockingQueue<>(300000)); }
配置参数(来自配置文件)
#ThreadPool corePool.Size=200 maxPool.Size=400 queue.Capacity=999999 KeepAlive=10
任务提交方法
public <T> Future<T> submitCall(Callable<T> callable) { logger.info("Submitting , total task {}, active count {} completed count {} queue size {}, threads in pool currently {}, largest thread pool {} ", threadPool.getTaskCount(), threadPool.getActiveCount(), threadPool.getCompletedTaskCount(), threadPool.getQueue().size(), threadPool.getPoolSize(), threadPool.getLargestPoolSize() ); return threadPool.submit(callable); }
日志信息
2024-11-27 13:46:33,963 [INFO ]---[DAExecutorService.java]---[http-nio-9201-exec-2]: Submitting , total task 200, active count 49 completed count 151 queue size 0, threads in pool currently 200, largest thread pool 200 2024-11-27 13:46:33,963 [INFO ]---[DAExecutorService.java]---[http-nio-9201-exec-2]: Submitting , total task 201, active count 49 completed count 151 queue size 1, threads in pool currently 200, largest thread pool 200 2024-11-27 13:46:33,964 [INFO ]---[DAExecutorService.java]---[http-nio-9201-exec-2]: Submitting , total task 202, active count 49 completed count 152 queue size 1, threads in pool currently 200, largest thread pool 200 2024-11-27 13:46:33,965 [INFO ]---[DAExecutorService.java]---[http-nio-9201-exec-2]: Submitting , total task 203, active count 49 completed count 152 queue size 2, threads in pool currently 200, largest thread pool 200 2024-11-27 13:46:33,966 [INFO ]---[DAExecutorService.java]---[http-nio-9201-exec-2]: Submitting , total task 204, active count 50 completed count 152 queue size 2, threads in pool currently 200, largest thread pool 200 2024-11-27 13:46:33,967 [INFO ]---[DAExecutorService.java]---[http-nio-9201-exec-2]: Submitting , total task 205, active count 50 completed count 152 queue size 3, threads in pool currently 200, largest thread pool 200
问题解答
这是Java ThreadPoolExecutor 的标准执行逻辑导致的,核心规则如下:
- 当线程池内线程数未达到核心线程数(
corePoolSize)时,新任务会直接触发创建新核心线程执行; - 当线程数已达到核心线程数后,新任务会优先进入任务队列,而非直接分配给空闲核心线程;
- 只有当任务队列已满,且线程数未达到最大线程数(
maxPoolSize)时,才会创建非核心线程执行任务。
回到你的场景:
- 核心线程数已经拉满到200,此时新提交的任务会先进入
LinkedBlockingQueue; - 日志中看到的队列size增加,是任务刚提交还未被空闲线程取走的瞬时状态——空闲的核心线程会主动从队列中拉取任务执行,从日志里的
completed count从151涨到152也能看出,已有空闲线程在处理队列中的任务; - 这类毫秒级的队列波动是正常现象,并非线程池没有复用空闲线程,只是任务提交和线程取任务的动作存在极短的时间差,被日志捕捉到了。
内容的提问来源于stack exchange,提问作者Muddassir Rahman
相关产品推荐
相关产品推荐

