目录
1. 创建异步任务
1.1 使用默认线程池
1.2 使用自定义线程池
2. 异步回调处理
2.1 thenApply 和 thenApplyAsync
2.2 thenAccept 和 thenAcceptAsync
2.3 thenRun 和 thenRunAsync
3. 异常处理
3.1 whenComplete 和 whenCompleteAsync
3.2 handle 和 handleAsync
4. 多任务组合
4.1 thenCombine 和 thenCombineAsync
4.2 thenAcceptBoth 和 thenAcceptBothAsync
4.3 runAfterBoth 和 runAfterBothAsync
以下是 CompletableFuture
的不同用法示例,包括注释、使用场景以及对比图:
1. 创建异步任务
1.1 使用默认线程池
// 使用 supplyAsync 创建一个有返回值的异步任务
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模拟耗时任务
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello, CompletableFuture!";
});
System.out.println(future.join()); // 阻塞等待任务完成并获取结果
使用场景:适用于简单的异步任务,不需要自定义线程池。
1.2 使用自定义线程池
ExecutorService customExecutor = Executors.newFixedThreadPool(4);
// 使用 supplyAsync 创建一个有返回值的异步任务,并指定自定义线程池
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
// 模拟耗时任务
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Hello, CompletableFuture with custom executor!";
}, customExecutor);
System.out.println(future.join()); // 阻塞等待任务完成并获取结果
使用场景:适用于需要对线程池进行精细控制的场景,例如限制线程数量或使用特定的线程池策略。
2. 异步回调处理
2.1 thenApply 和 thenApplyAsync
// 使用默认线程池
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello")
.thenApply(s -> s + " World"); // 同步回调
System.out.println(future1.join());
// 使用自定义线程池
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Hello", customExecutor)
.thenApplyAsync(s -> s + " World", customExecutor); // 异步回调
System.out.println(future2.join());
使用场景:适用于对异步任务的结果进行进一步处理,并且需要返回新的结果。 对比:thenApply
是同步回调,与父任务共享线程;thenApplyAsync
是异步回调,可能会启动新的线程。
2.2 thenAccept 和 thenAcceptAsync
// 使用默认线程池
CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> "Hello")
.thenAccept(s -> System.out.println(s + " World")); // 同步回调
future1.join();
// 使用自定义线程池
CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> "Hello", customExecutor)
.thenAcceptAsync(s -> System.out.println(s + " World"), customExecutor); // 异步回调
future2.join();
使用场景:适用于对异步任务的结果进行处理,但不需要返回新的结果。 对比:thenAccept
是同步回调,与父任务共享线程;thenAcceptAsync
是异步回调,可能会启动新的线程。
2.3 thenRun 和 thenRunAsync
// 使用默认线程池
CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> "Hello")
.thenRun(() -> System.out.println("Task completed")); // 同步回调
future1.join();
// 使用自定义线程池
CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> "Hello", customExecutor)
.thenRunAsync(() -> System.out.println("Task completed"), customExecutor); // 异步回调
future2.join();
使用场景:适用于在异步任务完成后执行某些操作,但不需要访问任务的结果。 对比:thenRun
是同步回调,与父任务共享线程;thenRunAsync
是异步回调,可能会启动新的线程。
3. 异常处理
3.1 whenComplete 和 whenCompleteAsync
// 使用默认线程池
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
if (new Random().nextInt(2) == 0) {
throw new RuntimeException("Error occurred");
}
return "Hello";
}).whenComplete((result, exception) -> {
if (exception != null) {
System.out.println("Exception: " + exception.getMessage());
} else {
System.out.println("Result: " + result);
}
});
future1.join();
// 使用自定义线程池
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
if (new Random().nextInt(2) == 0) {
throw new RuntimeException("Error occurred");
}
return "Hello";
}, customExecutor).whenCompleteAsync((result, exception) -> {
if (exception != null) {
System.out.println("Exception: " + exception.getMessage());
} else {
System.out.println("Result: " + result);
}
}, customExecutor);
future2.join();
使用场景:适用于需要在任务完成时(无论是正常完成还是异常完成)执行某些操作。 对比:whenComplete
是同步回调,与父任务共享线程;whenCompleteAsync
是异步回调,可能会启动新的线程。
3.2 handle 和 handleAsync
// 使用默认线程池
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
if (new Random().nextInt(2) == 0) {
throw new RuntimeException("Error occurred");
}
return "Hello";
}).handle((result, exception) -> {
if (exception != null) {
return "Default Value";
}
return result + " World";
});
System.out.println(future1.join());
// 使用自定义线程池
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
if (new Random().nextInt(2) == 0) {
throw new RuntimeException("Error occurred");
}
return "Hello";
}, customExecutor).handleAsync((result, exception) -> {
if (exception != null) {
return "Default Value";
}
return result + " World";
}, customExecutor);
System.out.println(future2.join());
使用场景:适用于需要对任务的结果或异常进行处理,并返回一个新的结果。 对比:handle
是同步回调,与父任务共享线程;handleAsync
是异步回调,可能会启动新的线程。
4. 多任务组合
4.1 thenCombine 和 thenCombineAsync
// 使用默认线程池
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello")
.thenCombine(CompletableFuture.supplyAsync(() -> " World"), (s1, s2) -> s1 + s2);
System.out.println(future1.join());
// 使用自定义线程池
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Hello", customExecutor)
.thenCombineAsync(CompletableFuture.supplyAsync(() -> " World", customExecutor), (s1, s2) -> s1 + s2, customExecutor);
System.out.println(future2.join());
使用场景:适用于需要将两个异步任务的结果组合成一个新的结果。 对比:thenCombine
是同步回调,与父任务共享线程;thenCombineAsync
是异步回调,可能会启动新的线程。
4.2 thenAcceptBoth 和 thenAcceptBothAsync
// 使用默认线程池
CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> "Hello")
.thenAcceptBoth(CompletableFuture.supplyAsync(() -> " World"), (s1, s2) -> System.out.println(s1 + s2));
future1.join();
// 使用自定义线程池
CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> "Hello", customExecutor)
.thenAcceptBothAsync(CompletableFuture.supplyAsync(() -> " World", customExecutor), (s1, s2) -> System.out.println(s1 + s2), customExecutor);
future2.join();
使用场景:适用于需要对两个异步任务的结果进行处理,但不需要返回新的结果。 对比:thenAcceptBoth
是同步回调,与父任务共享线程;thenAcceptBothAsync
是异步回调,可能会启动新的线程。
4.3 runAfterBoth 和 runAfterBothAsync
// 使用默认线程池
CompletableFuture<Void> future1 = CompletableFuture.supplyAsync(() -> "Hello")
.runAfterBoth(CompletableFuture.supplyAsync(() -> " World"), () -> System.out.println("Both tasks completed"));
future1.join();
// 使用自定义线程池
CompletableFuture<Void> future2 = CompletableFuture.supplyAsync(() -> "Hello", customExecutor)
.runAfterBothAsync(CompletableFuture.supplyAsync(() -> " World", customExecutor), () -> System.out.println("Both tasks completed"), customExecutor);
future2.join();
使用场景:适用于在两个异步任务都完成后执行某些操作,但不需要访问任务的结果。 对比:runAfterBoth
是同步回调,与父任务共享线程;runAfterBothAsync
是异步回调,可能会启动新的线程。
5.等待多个任务完成执行某个操作
CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
// 第一个异步操作
});
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
// 第二个异步操作
});
CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
allFutures.join(); // 阻塞直到所有异步操作完成
// 或者使用 thenRun 来在所有操作完成后执行某些操作
allFutures.thenRun(() -> System.out.println("All operations completed!"));
// 多线程分块处理
List<CompletableFuture<List<FtbCultivatePositionOrgStatisticesVO>>> futures = new ArrayList<>();
// 使用CompletableFuture.allOf等待所有任务完成
CompletableFuture<Void> allTasks = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
// 等待所有任务完成
allTasks.join();
// 收集所有任务的结果
List<FtbCultivatePositionOrgStatisticesVO> results = futures.stream()
.map(CompletableFuture::join)
.flatMap(Collection::stream)
.collect(Collectors.toList());
方法 | 描述 | 是否异步 | 是否需要线程池 | 返回值类型 | 使用场景 |
---|---|---|---|---|---|
supplyAsync | 创建一个有返回值的异步任务 | 是 | 可选 | CompletableFuture<U> | 需要异步执行并返回结果的任务,如查询数据库。 |
runAsync | 创建一个无返回值的异步任务 | 是 | 可选 | CompletableFuture<Void> | 需要异步执行但不需要返回结果的任务,如日志记录。 |
thenApply | 对任务结果进行处理,有返回值 | 否 | 否 | CompletableFuture<U> | 需要对任务结果进行转换或处理的场景,如数据格式转换。 |
thenApplyAsync | 对任务结果进行异步处理,有返回值 | 是 | 可选 | CompletableFuture<U> | 需要对任务结果进行复杂处理且不想阻塞当前线程的场景。 |
thenAccept | 对任务结果进行处理,无返回值 | 否 | 否 | CompletableFuture<Void> | 需要对任务结果进行处理但不需要返回值的场景,如打印日志。 |
thenAcceptAsync | 对任务结果进行异步处理,无返回值 | 是 | 可选 | CompletableFuture<Void> | 需要对任务结果进行处理但不需要返回值,且不想阻塞当前线程的场景。 |
thenRun | 任务完成后执行的操作,无入参,无返回值 | 否 | 否 | CompletableFuture<Void> | 任务完成后需要执行某些操作但不需要访问任务结果的场景。 |
thenRunAsync | 任务完成后异步执行的操作,无入参,无返回值 | 是 | 可选 | CompletableFuture<Void> | 任务完成后需要执行某些操作但不需要访问任务结果,且不想阻塞当前线程的场景。 |
whenComplete | 任务完成后执行的操作,可以访问任务结果或异常 | 否 | 否 | CompletableFuture<T> | 需要在任务完成后执行某些操作,无论任务是否成功。 |
whenCompleteAsync | 任务完成后异步执行的操作,可以访问任务结果或异常 | 是 | 可选 | CompletableFuture<T> | 需要在任务完成后执行某些操作,且不想阻塞当前线程。 |
handle | 任务完成后执行的操作,可以访问任务结果或异常,有返回值 | 否 | 否 | CompletableFuture<U> | 需要在任务完成后根据结果或异常返回新的值。 |
handleAsync | 任务完成后异步执行的操作,可以访问任务结果或异常,有返回值 | 是 | 可选 | CompletableFuture<U> | 需要在任务完成后根据结果或异常返回新的值,且不想阻塞当前线程。 |
thenCombine | 组合两个任务的结果,两个任务都完成后执行的操作,有返回值 | 否 | 否 | CompletableFuture<U> | 需要组合两个任务的结果并返回新的值。 |
thenCombineAsync | 组合两个任务的结果,两个任务都完成后异步执行的操作,有返回值 | 是 | 可选 | CompletableFuture<U> | 需要组合两个任务的结果并返回新的值,且不想阻塞当前线程。 |
thenAcceptBoth | 组合两个任务的结果,两个任务都完成后执行的操作,无返回值 | 否 | 否 | CompletableFuture<Void> | 需要组合两个任务的结果但不需要返回值。 |
thenAcceptBothAsync | 组合两个任务的结果,两个任务都完成后异步执行的操作,无返回值 | 是 | 可选 | CompletableFuture<Void> | 需要组合两个任务的结果但不需要返回值,且不想阻塞当前线程。 |
runAfterBoth | 两个任务都完成后执行的操作,无入参,无返回值 | 否 | 否 | CompletableFuture<Void> | 两个任务完成后需要执行某些操作但不需要访问任务结果。 |
runAfterBothAsync | 两个任务都完成后异步执行的操作,无入参,无返回值 | 是 | 可选 | CompletableFuture<Void> | 两个任务完成后需要执行某些操作但不需要访问任务结果,且不想阻塞当前线程。 |
applyToEither | 两个任务中任意一个完成后执行的操作,有返回值 | 否 | 否 | CompletableFuture<U> | 两个任务中任意一个完成后需要根据结果返回新的值。 |
applyToEitherAsync | 两个任务中任意一个完成后异步执行的操作,有返回值 | 是 | 可选 | CompletableFuture<U> | 两个任务中任意一个完成后需要根据结果返回新的值,且不想阻塞当前线程。 |
acceptEither | 两个任务中任意一个完成后执行的操作,无返回值 | 否 | 否 | CompletableFuture<Void> | 两个任务中任意一个完成后需要执行某些操作但不需要返回值。 |
acceptEitherAsync | 两个任务中任意一个完成后异步执行的操作,无返回值 | 是 | 可选 | CompletableFuture<Void> | 两个任务中任意一个完成后需要执行某些操作但不需要返回值,且不想阻塞当前线程。 |
runAfterEither | 两个任务中任意一个完成后执行的操作,无入参,无返回值 | 否 | 否 | CompletableFuture<Void> | 两个任务中任意一个完成后需要执行某些操作但不需要访问任务结果。 |
runAfterEitherAsync | 两个任务中任意一个完成后异步执行的操作,无入参,无返回值 | 是 | 可选 | CompletableFuture<Void> | 两个任务中任意一个完成后需要执行某些操作但不需要访问任务结果,且不想阻塞当前线程。 |
allOf | 等待多个任务都完成,无返回值 | 否 | 否 | CompletableFuture<Void> | 需要等待多个任务都完成后才继续执行。 |
anyOf | 等待多个任务中任意一个完成,有返回值 | 否 | 否 | CompletableFuture<Object> | 多个任务中任意一个完成后需要根据结果返回新的值。 |