使用while循环关闭ThreadPoolExecutor异常:循环未执行原因排查
问题分析与解决方案
你的代码核心错误出在while循环的条件逻辑上,导致循环根本没有执行的机会:
错误点拆解
循环条件逻辑矛盾
你的循环条件是!poolExecutor.isTerminated() && poolExecutor.getCompletedTaskCount() == 10,这要求两个条件必须同时成立才会进入循环。但主线程提交任务后立刻进入判断时,getCompletedTaskCount()的值还是0(任务尚未开始或完成),条件直接不成立,循环被跳过,主线程直接结束,线程池的核心线程因为未被调用shutdown(),会一直处于等待任务的状态。线程池核心线程的存活特性
你使用的线程池核心线程数为5,且未设置allowCoreThreadTimeOut(true),核心线程默认会一直存活,不会因为空闲时间超过keepAliveTime而销毁,所以主线程结束后它们会继续等待新任务。
正确实现方式
方式1:修正轮询逻辑(简单但非最优)
如果坚持用轮询,需要调整条件为等待完成任务数达到10,再调用shutdown():
public static void main(String[] args) { ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Thread-%d").build(); ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor( 5, 10, 0, TimeUnit.SECONDS, new SynchronousQueue<>(), threadFactory, new ThreadPoolExecutor.DiscardPolicy() ); // 提交10个短任务 for (int i = 0; i < 10; i++) { poolExecutor.submit(() -> { // 你的任务逻辑 System.out.println("任务执行完成"); }); } // 等待所有10个任务完成 while (poolExecutor.getCompletedTaskCount() < 10) { try { Thread.sleep(50); // 短暂休眠避免空轮询占用CPU } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } poolExecutor.shutdown(); }
方式2:使用CountDownLatch(推荐,更高效)
轮询会浪费CPU资源,用CountDownLatch可以精准等待所有任务完成,是更优雅的实现:
public static void main(String[] args) throws InterruptedException { ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Thread-%d").build(); ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor( 5, 10, 0, TimeUnit.SECONDS, new SynchronousQueue<>(), threadFactory, new ThreadPoolExecutor.DiscardPolicy() ); CountDownLatch taskLatch = new CountDownLatch(10); // 提交10个任务,每个任务完成后触发countDown for (int i = 0; i < 10; i++) { poolExecutor.submit(() -> { try { // 你的任务逻辑 System.out.println("任务执行完成"); } finally { taskLatch.countDown(); // 确保任务无论成功失败都计数 } }); } taskLatch.await(); // 阻塞主线程,直到所有任务完成 poolExecutor.shutdown(); }
内容的提问来源于stack exchange,提问作者Xbai-hang
相关产品推荐
相关产品推荐

