completablefuture 实现了 future 接口并扩展了异步编程模型,核心区别在于它支持链式调用、自动完成和组合操作,而 future 仅能阻塞等待结果。使用 completablefuture 时,通过 supplyasync 提交任务,利用 thenapply 或 thencompose 串联逻辑,无需轮询或阻塞即可处理结果。

Future 的阻塞与中断问题如何解决
Future 的 get() 方法会阻塞当前线程直到结果可用,且无法优雅取消正在执行的任务。CompletableFuture 提供了 isDone() 检查状态,并通过 cancel() 尝试中断,但更推荐用 thenAccept 注册回调来避免阻塞。例如,当任务失败时,使用 exceptionally 捕获异常而非 catch InterruptedException。

import java.util.concurrent.CompletableFuture;
public class Demo {
public static void main(String[] args) {
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try { Thread.sleep(1000); } catch (InterruptedException e) {}
return "Result";
});
future.thenAccept(res -> System.out.println(res))
.exceptionally(e -> { System.err.println("Error"); return null; });
try { Thread.sleep(2000); } catch (InterruptedException e) {}
}
}
如何组合多个异步任务的结果
结合多个 Future 需要手动处理同步,而 CompletableFuture 提供 allOf 和 anyOf 静态方法。allOf 等待所有任务完成,anyOf 在任一任务完成时触发。对于依赖前一步结果的场景,thenCompose 比 flatMap 更直观。例如,先获取用户 ID 再获取详情,使用 thenCompose 链接两个异步调用。
立即学习“Java免费学习笔记(深入)”;

import java.util.concurrent.CompletableFuture;
public class CombineDemo {
public static void main(String[] args) {
CompletableFuture<Integer> idFuture = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<String> detailFuture = idFuture.thenCompose(id ->
CompletableFuture.supplyAsync(() -> "Detail for " + id)
);
detailFuture.thenAccept(System.out::println);
try { Thread.sleep(1000); } catch (InterruptedException e) {}
}
}
CompletableFuture 默认使用哪个线程池
如果不指定 Executor,CompletableFuture 使用 ForkJoinPool.commonPool(),该池大小等于 CPU 核心数减一。这可能导致长耗时任务阻塞其他任务。建议为 IO 密集型任务传入自定义 ThreadPoolExecutor,如 Executors.newFixedThreadPool(10),以隔离资源并提高吞吐量。


















