Callable可返回结果并抛异常,Runnable不能;需用ExecutorService.submit()提交Callable获取Future,再调用get()阻塞获取结果、isDone()轮询状态、cancel()中断任务。

Java 中通过 Callable 和 Future 创建有返回值的线程,核心是用线程池执行 Callable 任务,并通过 Future 获取异步执行结果。
为什么不能直接用 Runnable?
Runnable 的 run() 方法没有返回值、也不能抛出受检异常;而 Callable 的 call() 方法可以返回任意类型结果(泛型支持),且允许抛出异常,更适合需要结果的场景。
基本步骤:提交 Callable,获取 Future
使用 ExecutorService(如 Executors.newFixedThreadPool())调用 submit() 方法提交 Callable,它会立即返回一个 Future 对象:
-
Future.get()会阻塞当前线程,直到任务完成并返回结果 -
Future.isDone()可轮询判断是否执行完毕 -
Future.cancel(true)可尝试中断正在运行的任务
一个完整示例
下面是一个计算阶乘并返回结果的简单例子:
立即学习“Java免费学习笔记(深入)”;
import java.util.concurrent.*;
public class CallableExample {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
// 定义 Callable 任务(返回 Long 类型)
Callable<Long> task = () -> {
long result = 1;
for (int i = 1; i <= 10; i++) {
result *= i;
}
return result; // 返回计算结果
};
// 提交任务,获得 Future
Future<Long> future = executor.submit(task);
// 获取结果(会阻塞,直到任务完成)
Long result = future.get();
System.out.println("10! = " + result);
executor.shutdown();
}
}
注意事项和常见问题
-
Future.get()是阻塞操作,若任务耗时长或未完成,调用线程会一直等待;可用get(long timeout, TimeUnit unit)设置超时避免无限等待 - 任务抛出异常时,
get()会包装为ExecutionException抛出,需捕获处理 -
ExecutorService使用完必须调用shutdown()或shutdownNow(),否则 JVM 不会退出 - 多个
Future可用ExecutorCompletionService实现“谁先完成谁先处理”,适合批量任务结果收集


















