Java中Callable接口支持返回结果和抛出异常,需配合ExecutorService与Future使用;可提交单个任务通过future.get()获取结果,或批量调用invokeAll();还可结合CompletableFuture实现链式异步编排。

Java中使用Callable接口实现异步任务,核心在于它能返回结果并支持抛出异常,比Runnable更适用于需要获取执行结果的场景。通常配合ExecutorService和Future使用。
Callable接口的基本用法
Callable是一个泛型接口,只定义了一个call()方法,返回指定类型的值,且可声明抛出受检异常:
public interface Callable<V> {
V call() throws Exception;
}
例如,定义一个计算阶乘的异步任务:
Callable<Long> factorialTask = () -> {
long result = 1;
for (int i = 1; i <= 5; i++) {
result *= i;
}
return result;
};
提交Callable任务并获取结果
通过ExecutorService的submit()方法提交Callable,返回Future对象,用于查询状态、获取结果或取消任务:
立即学习“Java免费学习笔记(深入)”;
- 调用
future.get()会阻塞当前线程,直到任务完成;可设置超时避免无限等待 - 调用
future.isDone()判断是否执行完毕 - 调用
future.cancel(true)尝试中断正在运行的任务
示例:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Long> future = executor.submit(factorialTask);
try {
Long result = future.get(3, TimeUnit.SECONDS); // 最多等3秒
System.out.println("结果:" + result);
} catch (TimeoutException e) {
System.out.println("任务超时");
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
} finally {
executor.shutdown();
}
批量提交多个Callable任务
使用invokeAll()可一次性提交多个Callable,返回List<Future<V>>,所有任务并发执行,方法调用会阻塞直到全部完成(或超时):
List<Callable<Integer>> tasks = Arrays.asList(
() -> { Thread.sleep(100); return 1; },
() -> { Thread.sleep(200); return 2; },
() -> { Thread.sleep(150); return 3; }
);
List<Future<Integer>> futures = executor.invokeAll(tasks, 500, TimeUnit.MILLISECONDS);
for (Future<Integer> f : futures) {
if (!f.isCancelled()) {
System.out.println(f.get()); // 按提交顺序获取结果
}
}
结合CompletableFuture做更灵活的异步编排
从Java 8起,CompletableFuture提供了更强大的异步编程能力,可替代原始Future的阻塞式等待:
- 用
CompletableFuture.supplyAsync()直接包装Callable逻辑(实际接受Supplier,但语义接近) - 支持链式调用:
thenApply、thenAccept、exceptionally等 - 可组合多个异步任务:
thenCompose、allOf、anyOf
示例:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
return "Hello";
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).thenApply(s -> s + " World")
.exceptionally(t -> "Error: " + t.getMessage());
System.out.println(future.join()); // 非阻塞等待+获取结果










