Java8使用CompletableFuture实现异步方法顺序执行的问题咨询
问题原因
- 回调依赖关系错误:你将Thread2和Thread3的回调都注册到了Thread1对应的
CompletableFuture实例上,二者是平级并行触发的关系,不存在Thread3依赖Thread2执行完成的逻辑,自然不会按1→2→3的顺序执行。 thenRunAsync未指定自定义线程池:代码中两次调用thenRunAsync都没有传入你定义的单线程池,默认会使用ForkJoinPool.commonPool()多线程池,两个任务会被分配到不同线程并行执行,所以会出现输出交替的情况。- 线程池关闭时机错误:你将线程池关闭的回调注册到了Thread1的Future上,Thread1执行完成就会触发关闭,但此时后续的Thread2、Thread3任务还在公共线程池中运行,不符合执行完成再回收资源的逻辑。
正确实现方案
要实现异步任务按顺序执行,必须让每一步的回调都注册到上一步返回的CompletableFuture上,形成链式依赖,同时统一指定线程池避免并行执行:
import org.jetbrains.annotations.NotNull; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Main { public static void main(String[] args) { System.out.println("CompletableFuture"); ExecutorService e = Executors.newSingleThreadExecutor(r -> new Thread(r, "single Thread")); // 第一步:执行Thread1,返回对应Future CompletableFuture<Void> step1 = CompletableFuture.runAsync(() -> print("thread 1"), e); // 第二步:step1完成后执行Thread2,返回当前步骤Future CompletableFuture<Void> step2 = runT(step1, e); // 第三步:step2完成后执行Thread3,返回当前步骤Future CompletableFuture<Void> step3 = step2.thenRunAsync(() -> print("Thread 3"), e); // 所有步骤完成后关闭线程池 step3.thenRun(e::shutdown); } public static void print(String threadName){ for(int i=1;i<=10;i++) { System.out.println(threadName + ":" + i); } } // 接收上一步的Future,返回当前步骤执行完成的Future public static CompletableFuture<Void> runT(@NotNull CompletableFuture<Void> prevStep, ExecutorService executor){ return prevStep.thenRunAsync(() -> print("Thread 2"), executor); } }
内容的提问来源于stack exchange,提问作者Sridhar Karuppusamy
相关产品推荐
相关产品推荐

