Java Executor Service如何等待所有任务执行完成?
如何等待ExecutorService的所有任务执行完成?
我使用Executor Service同时运行10个任务,每次执行2个任务,代码如下:
ExecutorService executor = Executors.newFixedThreadPool(2); for (int i = 0; i < 10; i++) { String name = "NamePrinter " + i; Runnable runner = new TaskPrint(name, 1000); System.out.println("Adding: " + name + " / " + 1000); executor.execute(runner); }请问如何等待所有任务执行完成?
这里有几种可靠的方法可以实现需求,你可以根据场景选择最合适的:
方法一:使用shutdown() + awaitTermination()(推荐)
这是最标准、最常用的做法,步骤清晰且符合ExecutorService的设计规范:先关闭服务不再接收新任务,再等待已提交的任务全部执行完毕。
executor.shutdown(); // 停止接收新任务,已提交的任务会继续执行 try { // 等待所有任务完成,这里设置1小时超时,可根据任务实际耗时调整 if (!executor.awaitTermination(1, TimeUnit.HOURS)) { // 超时未完成时,强制中断剩余任务 executor.shutdownNow(); // 再等待一段时间,确保中断后的任务能收尾 if (!executor.awaitTermination(1, TimeUnit.MINUTES)) { System.err.println("ExecutorService 未能正常终止"); } } } catch (InterruptedException e) { // 当前线程被中断时,同步中断Executor的所有任务 executor.shutdownNow(); // 保留当前线程的中断状态,交给上层逻辑处理 Thread.currentThread().interrupt(); }
方法二:使用invokeAll()
如果可以提前把所有任务收集成Callable列表,invokeAll()会直接阻塞主线程,直到所有任务完成或超时。对于你的Runnable任务,用Executors.callable()就能轻松转换:
List<Callable<Void>> tasks = new ArrayList<>(); for (int i = 0; i < 10; i++) { String name = "NamePrinter " + i; Runnable runner = new TaskPrint(name, 1000); System.out.println("Adding: " + name + " / " + 1000); tasks.add(Executors.callable(runner)); } ExecutorService executor = Executors.newFixedThreadPool(2); try { // 阻塞直到所有任务完成,或超过1小时超时 executor.invokeAll(tasks, 1, TimeUnit.HOURS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { executor.shutdown(); }
方法三:使用CountDownLatch
如果需要更灵活的多线程同步控制(比如多个线程等待同一批任务完成),CountDownLatch是很好的选择。初始化计数器为任务总数,每个任务执行完毕后调用countDown(),主线程通过await()等待计数器归0:
CountDownLatch latch = new CountDownLatch(10); // 任务总数为10 ExecutorService executor = Executors.newFixedThreadPool(2); for (int i = 0; i < 10; i++) { String name = "NamePrinter " + i; Runnable runner = new Runnable() { @Override public void run() { try { new TaskPrint(name, 1000).run(); } finally { latch.countDown(); // 任务完成,计数器减1 } } }; System.out.println("Adding: " + name + " / " + 1000); executor.execute(runner); } try { latch.await(); // 等待所有任务完成,计数器变为0 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { executor.shutdown(); }
选择建议
- 优先用方法一,它是ExecutorService的标准终止流程,简洁安全,覆盖了大部分常规场景。
- 如果一开始就能收集所有任务,方法二的代码会更直观。
- 方法三适合复杂的多线程同步场景,比如需要多个线程等待同一批任务结束后再执行后续逻辑。
内容的提问来源于stack exchange,提问作者Jobs
相关产品推荐
相关产品推荐

