thenRun用于前序异步任务成功完成且无需其结果时执行无参无返回值操作,如日志、通知;默认同线程执行,耗时操作应选thenRunAsync并可指定线程池。

thenRun 是 CompletableFuture 提供的一个回调方法,用于在前一个异步任务**成功完成(不关心返回值)后,执行一个无参、无返回值的后续动作。
什么时候用 thenRun?
当你只需要“做点什么”,比如记录日志、发通知、更新 UI 状态,而不需要前一步的结果,也不需要把结果传给下一步时,thenRun 就很合适。它比 thenAccept(需要参数)和 thenApply(需要返回值)更轻量。
基本用法:链式调用
直接在 CompletableFuture 后调用 thenRun(Runnable):
CompletableFuture.supplyAsync(() -> {
System.out.println("正在计算...");
try { Thread.sleep(1000); } catch (InterruptedException e) {}
return 42;
})
.thenRun(() -> {
System.out.println("计算已完成,执行清理或通知操作");
});
注意:thenRun 中的 Runnable 在前一个任务完成的同一个线程上执行(默认 ForkJoinPool),除非你显式指定异步版本(见下一条)。
立即学习“Java免费学习笔记(深入)”;
异步执行 thenRun:避免阻塞前序线程
如果后续动作耗时或可能阻塞,建议用 thenRunAsync,它会将 Runnable 提交到另一个线程(默认 ForkJoinPool.commonPool(),也可传入自定义 Executor):
CompletableFuture.supplyAsync(() -> {
return fetchDataFromDB(); // 模拟耗时 IO
})
.thenRunAsync(() -> {
sendSuccessNotification(); // 不想让这个拖慢主线程
}, Executors.newCachedThreadPool()); // 可选:指定线程池
注意事项
-
不接收上游结果:如果你需要上一步的返回值,请改用
thenAccept或thenApply -
不处理异常:如果上游任务抛出异常,
thenRun不会被触发;需搭配exceptionally或handle做错误兜底 -
返回新的 CompletableFuture:
thenRun返回的是CompletableFuture<void></void>,可用于继续链式调用(如再接一个thenRun)


















