CompletableFuture
创建线程方式
- 继承 Thread
- 实现 Runnable
- 实现 Callable,线程也能有返回值,必须搭配线程池或 FutureTask 使用
Callable 示例
FutureTask<Integer> futureTask = new FutureTask<>(() -> 123);
new Thread(futureTask).start();
System.out.println(futureTask.isDown()); // 线程是否运行结束
System.out.println(futureTask.get()); // get 会阻塞,等待线程运行结束
FutureTask 有缺陷,获取结果调用 get 方法会阻塞,并不知道什么时候能结束,倒是提供了一个 isDone 方法用来判断是否结束,但是在代码中死循环来判断任务是否结束,不优雅,并且也会增加 CPU 空转
CompletableFuture
- 非阻塞获取线程处理结果:任务完成后执行回调函数获取结果而不是阻塞
- 组合任务:使用
thenApply
、thenCombine
等方法将多个异步任务组合起来 - 异常处理:提供了
handle
和exceptionally
方法来处理任务执行过程中可能发生的异常
常用方法
-
supplyAsync:创建一个 CompletableFuture,有返回值
CompletableFuture.supplyAsync(() -> { // 异步执行的任务 return "Hello"; });
-
runAsync:创建一个 CompletableFuture,没有返回值
CompletableFuture.runAsync(() -> { // 异步执行的任务,没有返回值 });
-
thenApply:处理前一个任务的结果,有返回值
CompletableFuture.supplyAsync(() -> "Hello") .thenApply(result -> result + " World");
-
thenAccept:处理前一个任务的结果,没有返回值
CompletableFuture.supplyAsync(() -> "Hello") .thenAccept(result -> System.out.println(result));
-
thenCombine:串联一个任务
处理完后根据是否需要返回值,选择继续调用 thenApply 或 thenAccept
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 5); CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 10); future1.thenCombine(future2, (result1, result2) -> result1 + result2) .thenAccept(sum -> System.out.println("Sum: " + sum));
-
allOf:等待所有任务完成
thenCombine 要拿到 CompletableFuture 的结果,allOf 不需要
有 CountDownLatch、Semaphore 的意味
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> System.out.println("Task 1")); CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> System.out.println("Task 2")); // 主线程此时阻塞住,join 和 get 作用相同,都是阻塞等待结果,区别是 join 不用捕获异常 CompletableFuture.allOf(future1, future2).join();
-
anyOf:看谁跑得快,用于处理多个任务中最先完成的一个任务的结果
applyToEither 是两个任务中看谁跑得快,anyOf 是多个任务
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 1); CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 2); CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> 3); // 多个任务看谁跑得快 CompletableFuture<Object> anyOf = CompletableFuture.anyOf(future1, future2, future3); anyOf.thenAccept(result -> System.out.println("Any result: " + result)); // 两个任务看谁跑得快 CompletableFuture<Integer> resultFuture = future1 .applyToEither(future2, result -> result * 10);
-
exceptionally:捕获异常处理
CompletableFuture.supplyAsync(() -> { if (true) throw new RuntimeException("Error"); return "Success"; }).exceptionally(ex -> { System.err.println("Exception: " + ex.getMessage()); return "Fallback"; });
-
whenComplete:两个功能,1:任务完成后回调;2:捕获异常处理(exceptionally 的功能)
CompletableFuture.supplyAsync(() -> { if (true) throw new RuntimeException("Something went wrong"); return "Success"; }).whenComplete((result, ex) -> { // 任务完成或异常走这里 if (ex != null) { // 当没有异常 System.err.println("Failed with exception: " + ex.getMessage()); } else { // 当发生异常 System.out.println("Completed successfully with result: " + result); } });
-
handle:如果发生异常,可以不影响整个链的执行
thenApply 示例,当其中一个任务异常,会印象整个链:
public static void main(String[] args){ CompletableFuture.supplyAsync(() -> 5) // 任务 1( 返回5 ) .thenApply((v) -> v + 10) // 任务 2(返回 5+10 ) .thenApply((v) -> v / 0) // 任务 3 (返回 15/0,报错 ) .thenApply((v) -> v + 10) // 任务 4 .whenComplete((r, e) -> { System.out.println(r); }); } // 打印 null,链中一个错误,会影响整个链
handle 示例:
public static void main(String[] args) { CompletableFuture.supplyAsync(() -> 5) // 任务 1 .thenApply((v) -> v / 0) // 任务 2(异常) .thenApply((v) -> v + 10) // 任务 3 .handle((r, e) -> { // 前面的任务(任务1、任务2、任务3任意一个)是否有异常 if (e != null) { return 0; } else { return r; } }) .thenApply((v) -> v + 10) // 任务 4 .whenComplete((r, e) -> { System.out.println(r); }); } // 打印 10
分类:
JAVA - JUC
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具