Callable 和 Future 配合用于提交有返回值的异步任务:Callable 实现带返回值和异常的任务,Future 提供状态查询与结果获取能力,通过 ExecutorService 提交并调用 get()、isDone() 等方法处理结果。

在 Java 多线程中,Callable 和 Future 是配合使用的标准方式,用于提交有返回值的任务并获取其异步执行结果。与不返回值的 Runnable 不同,Callable 允许任务返回结果、抛出受检异常,而 Future 则提供对任务状态的查询和结果的获取能力。
1. 实现 Callable 接口定义带返回值的任务
Callable 是一个泛型接口,只有一个 call() 方法,需返回指定类型的值(如 String、Integer 等),且可以抛出异常:
Callable<Integer> task = () -> {
Thread.sleep(1000);
return 42; // 返回计算结果
};
注意:call() 方法不能像 run() 那样直接传给 Thread 构造器,必须通过线程池提交。
2. 使用 ExecutorService 提交任务并获取 Future 对象
通过 ExecutorService.submit() 提交 Callable,会立即返回一个 Future 实例,代表尚未完成的异步计算:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
ExecutorService executor = Executors.newSingleThreadExecutor(); Future<Integer> future = executor.submit(task); // 后续可随时检查或获取结果
Future 是“未来结果”的占位符,此时任务可能正在运行、已结束,甚至还没开始。
3. 通过 Future 获取执行结果的三种常用方式
-
get():阻塞当前线程,直到任务完成并返回结果;若任务被取消或执行出错,会抛出CancellationException或ExecutionException(包装原始异常) -
get(long timeout, TimeUnit unit):带超时的阻塞获取,超时未完成则抛出TimeoutException,适合防止无限等待 -
isDone()/isCancelled():非阻塞查询任务状态,常用于轮询或条件判断(但应避免 busy-wait)
4. 完整示例:提交任务、等待结果、处理异常
ExecutorService executor = Executors.newFixedThreadPool(2);
Callable<String> task = () -> {
Thread.sleep(2000);
if (Math.random() > 0.8) throw new RuntimeException("模拟失败");
return "任务完成,结果为:" + System.currentTimeMillis();
};
Future<String> future = executor.submit(task);
try {
String result = future.get(3, TimeUnit.SECONDS); // 最多等 3 秒
System.out.println(result);
} catch (TimeoutException e) {
System.err.println("任务超时,被取消");
future.cancel(true); // 中断执行中的线程
} catch (ExecutionException e) {
System.err.println("任务执行异常:" + e.getCause().getMessage());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.err.println("当前线程被中断");
} finally {
executor.shutdown();
}
关键点:务必处理 ExecutionException(包装任务内抛出的异常)、InterruptedException(调用线程被中断),以及合理使用超时机制避免死等。

















