supplyasync执行有返回值异步任务,返回completablefuture,适合链式处理;runasync执行无返回值任务,返回completablefuture,适合发通知等场景;两者默认用forkjoinpool.commonpool(),可传入自定义executor控制线程资源。

supplyAsync 用于执行有返回值的异步任务,runAsync 用于执行无返回值的异步任务,两者都默认使用 ForkJoinPool.commonPool(),但可通过传入自定义 Executor 精确控制线程资源。
supplyAsync:带返回值的异步任务
适合需要后续链式处理(如 thenApply、thenCompose)的场景。它接收一个 Supplier<t></t>,返回 CompletableFuture<t></t>。
- 基础用法:CompletableFuture
future = CompletableFuture.supplyAsync(() -> "hello"); - 指定线程池:CompletableFuture.supplyAsync(() -> doHeavyWork(), myExecutor);
- 常见搭配:future.thenApply(s -> s.toUpperCase()).thenAccept(System.out::println);
runAsync:不带返回值的异步任务
适合“只管执行、无需结果”的场景,例如发通知、写日志、清理缓存等。它接收一个 Runnable,返回 CompletableFuture<void></void>(实际是 CompletableFuture>,泛型为 Void,不可被后续 thenApply 使用)。
- 基础用法:CompletableFuture
future = CompletableFuture.runAsync(() -> System.out.println("done")); - 指定线程池:CompletableFuture.runAsync(() -> sendEmail(), emailExecutor);
- 后续处理建议用
thenRun或thenAccept(若上游有值):future.thenRun(() -> log("sent"));
组合多个异步任务的关键技巧
编排的核心在于区分「串行依赖」和「并行聚合」:
- 串行(上一个完成才触发下一个):supplyAsync(...).thenCompose(result -> supplyAsync(() -> process(result)))
- 并行且等待全部完成:CompletableFuture.allOf(f1, f2, f3).join();(注意:allOf 返回
CompletableFuture<void></void>,需手动获取各结果) - 并行并收集结果:List
> futures = ...; CompletableFuture (需自行封装- > all = sequence(futures);
sequence方法)
注意事项与避坑点
- 不要忽略异常:未显式处理时,异常会静默丢失。务必用
exceptionally、handle或whenComplete - 避免在
supplyAsync中执行阻塞操作(如数据库查询、HTTP 调用),除非配了专用线程池;否则会拖垮commonPool -
runAsync的返回值是CompletableFuture<void></void>,不能直接thenApply,要用thenRun或转成有值的链路(例如用thenCompose包一层supplyAsync) - 记得主动管理线程池生命周期:自定义
ExecutorService用完后应调用shutdown()
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











