Java线程池提交Callable任务需调用ExecutorService.submit()获取Future,再通过get()阻塞获取结果;须处理InterruptedException、ExecutionException和TimeoutException;批量任务推荐用CompletionService按完成顺序获取结果;使用后应调用shutdown()和awaitTermination()关闭线程池。

Java 中线程池提交 Callable 任务并用 Future 获取返回值,核心是调用 ExecutorService.submit() 方法,它会立即返回一个 Future 对象,后续通过该对象的 get() 方法阻塞获取结果。
使用 submit(Callable) 提交并获取 Future
submit() 是 ExecutorService 提供的专门用于接收 Callable(带返回值、可抛异常)任务的方法。它和只接受 Runnable 的 execute() 不同,返回值类型就是 Future<T>,其中 T 是 Callable 的泛型返回类型。
- 创建线程池:推荐用
Executors.newFixedThreadPool(3)或更安全的ThreadPoolExecutor手动构造 - 定义
Callable<String>:比如耗时计算后返回字符串 - 调用
service.submit(callable)→ 得到Future<String> - 调用
future.get()阻塞等待结果;也可用get(long, TimeUnit)设置超时避免无限等待
处理 get() 的异常和超时
Future.get() 可能抛出三种受检异常,实际使用中必须处理:
-
InterruptedException:当前线程在等待时被中断 -
ExecutionException:任务执行过程中抛出了未捕获异常(包装在该异常中,可通过getCause()获取原始异常) -
TimeoutException(仅限带超时的get()):任务未在指定时间内完成
建议始终用 try-catch 包裹 get(),尤其生产环境要避免因任务异常导致主线程崩溃。
立即学习“Java免费学习笔记(深入)”;
批量提交多个 Callable 并收集结果
若需并发执行多个有返回值的任务,可循环调用 submit() 得到多个 Future,再逐个调用 get() 获取结果:
- 注意:
get()是阻塞的,按顺序调用会导致“等待最慢任务拖慢整体” - 优化方式:先全部
submit(),再统一get();或用CompletionService(如ExecutorCompletionService)自动按完成顺序获取结果 -
CompletionService示例:构造时传入线程池,调用submit()后用take()或poll()拿最先完成的Future
别忘了关闭线程池
使用完 ExecutorService 后应显式关闭,否则 JVM 不会退出(因为线程池中的工作线程是守护线程以外的非守护线程):
- 调用
shutdown():停止接收新任务,但会等已有任务执行完 - 调用
awaitTermination(long, TimeUnit)等待所有任务结束(建议配合超时) - 必要时调用
shutdownNow()尝试中断正在执行的任务(不保证一定成功)
典型收尾写法:service.shutdown(); if (!service.awaitTermination(5, SECONDS)) service.shutdownNow();


















