想要等所有任务执行完可以使用allOf
效果图

这里的结果是来自三个线程的叠加,但是吧
代码部分
package com.java.test260426;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.CompletableFuture;/*** @Description: 等所有任务执行完* @Author: tutu-qiuxie* @Create: 2026/4/26 16:38*/
@Slf4j
public class allOfTest {public static void main(String[] args) {CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {sleep(2000);log.info("打印f1..");return "结果1";});CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {sleep(3000);log.info("打印f2..");return "结果2";});CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {sleep(1000);log.info("打印f3..");return "结果3";});// 核心:等待全部完成CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);log.info("主线程继续执行...");// 阻塞直到全部完成all.join();// 手动拿结果(重点!!!)String r1 = f1.join();String r2 = f2.join();String r3 = f3.join();log.info(r1 + " | " + r2 + " | " + r3);}private static void sleep(long time){try {Thread.sleep(time);} catch (InterruptedException e) {e.printStackTrace();}}
}
他有个比较大的问题,异常会自己吞掉,这样我们就没法知道哪里出了问题,

看,这样我们就比较清楚问题在哪里了,
代码部分
package com.java.test260426;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.CompletableFuture;/*** @Description:* @Author: tutu-qiuxie* @Create: 2026/4/26 21:14*/
@Slf4j
public class allOfTest001 {public static void main(String[] args) {CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {sleep(2000);log.info("打印f1..");int age = -1;if (age < 0) {throw new BizException("年龄不能为负数");}return "结果1";}).exceptionally(e->{log.error("f1发生异常:", e);return "默认1";});CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {sleep(3000);log.info("打印f2..");return "结果2";}).exceptionally(e-> {log.error("f2发生异常:", e);return "默认2";});CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {sleep(1000);log.info("打印f3..");return "结果3";}).exceptionally(e-> {log.error("f3发生异常:", e);return "默认3";});// 核心:等待全部完成CompletableFuture<Void> all = CompletableFuture.allOf(f1, f2, f3);log.info("主线程继续执行...");// 阻塞直到全部完成all.join();// 手动拿结果(重点!!!)String r1 = f1.join();String r2 = f2.join();String r3 = f3.join();log.info(r1 + " | " + r2 + " | " + r3);}private static void sleep(long time){try {Thread.sleep(time);} catch (InterruptedException e) {e.printStackTrace();}}}
还有就是使用的是默认的线程池,
- 线程数有限
- IO任务会把线程占死
- 高并发直接卡死
所以最好使用自定义的
代码部分
ExecutorService pool = Executors.newFixedThreadPool(10);CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {sleep(2000);log.info("打印f1..");int age = -1;if (age < 0) {throw new BizException("年龄不能为负数");}return "结果1";}, pool) // ✅ 线程池用在这里.handleAsync((res, e) -> {if (e != null) {log.error("f1发生异常:", e);return "默认1";}return res;}, pool); // ✅ 这里也可以指定线程池
如果某个任务没有结束,会一直卡住,因此这个问题需要处理

这里设置了任务超时时间,如果超了就结束
代码部分
package com.java.test260426;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;/*** @Description:* @Author: tutu-qiuxie* @Create: 2026/4/26 21:14*/
@Slf4j
public class allOfTest001 {private static final ScheduledExecutorService scheduler =Executors.newScheduledThreadPool(1);public static <T> CompletableFuture<T> timeoutAfter(long timeout, TimeUnit unit) {CompletableFuture<T> result = new CompletableFuture<>();scheduler.schedule(() -> {result.completeExceptionally(new TimeoutException("超时了"));}, timeout, unit);return result;}public static void main(String[] args) {ExecutorService pool = Executors.newFixedThreadPool(10);// ================= f1 =================CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {sleep(2000);log.info("打印f1..");return "结果1";}, pool).handleAsync((res, e) -> {if (e != null) {log.error("f1发生异常:", e);return "默认1";}return res;}, pool);// ================= f2 =================CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {sleep(3000);log.info("打印f2..");return "结果2";}, pool) // ✅ 必须加线程池.exceptionally(e -> {log.error("f2发生异常:", e);return "默认2";});// ================= f3 =================CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {sleep(1000);log.info("打印f3..");return "结果3";}, pool) // ✅ 必须加线程池.exceptionally(e -> {log.error("f3发生异常:", e);return "默认3";});// ================= allOf + 超时 =================CompletableFuture<Void> all =CompletableFuture.allOf(f1, f2, f3);// 👉 Java8超时写法CompletableFuture<Void> finalResult =all.applyToEither(timeoutAfter(2, TimeUnit.SECONDS), v -> v);try {finalResult.join();// 正常拿结果String r1 = f1.join();String r2 = f2.join();String r3 = f3.join();log.info("结果:{}, {}, {}", r1, r2, r3);} catch (Exception e) {log.error("整体执行超时或异常", e);}}private static void sleep(long time){try {Thread.sleep(time);} catch (InterruptedException e) {e.printStackTrace();}}}
就是处理并行,我们可能会使用多个备选,确保我们服务一直可以用,比如支付方面,会选择支付宝,微信,等多种方式
这里就会用到anyOf

哪个最快,返回哪个
代码部分
package com.java.test260426;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.CompletableFuture;/*** @Description: 谁先完成用谁* @Author: tutu-qiuxie* @Create: 2026/4/26 17:08*/
@Slf4j
public class anyOfTest {public static void main(String[] args) throws Exception {CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {sleep(3);log.info("打印f1..");return "慢任务";});CompletableFuture<String> f2 = CompletableFuture.supplyAsync(() -> {sleep(1);log.info("打印f2..");return "快任务";});CompletableFuture<String> f3 = CompletableFuture.supplyAsync(() -> {sleep(2);log.info("打印f3..");return "中等任务";});// 核心:谁先完成用谁CompletableFuture<Object> any = CompletableFuture.anyOf(f1, f2, f3);log.info("主线程继续执行...");Object result = any.join();log.info("最先返回结果:" + result);}private static void sleep(int seconds) {try {Thread.sleep(seconds * 1000);} catch (InterruptedException e) {e.printStackTrace();}}}
下面给出两者区别

