方法在CompletableFuture的whenComplete执行前返回,如何实现顺序执行?
问题根因
你当前的写法是提交异步任务后没有等待任务执行完成就直接返回结果,异步任务的执行逻辑和主线程并行,因此会先执行return语句,此时whenComplete的逻辑还未执行,自然拿不到赋值结果。
解决方案
方案1:同步阻塞获取结果(无需处理InterruptedException)
如果你需要当前方法同步返回结果,直接使用join()方法即可,它的功能和get()完全一致,唯一区别是不会抛出受检异常InterruptedException,仅会抛出非受检的CompletionException,符合你的要求:
String myOutput = CompletableFuture.supplyAsync(() -> callMyRestService(myUrl)) .whenComplete((myResponseWrapper, exception) -> { if (exception != null) { logUtil.error("GET", exception.toString()); } }) .thenApply(myResponseWrapper -> myResponseWrapper != null ? myResponseWrapper.getName() : null) .join(); return myOutput;
- 注意不要通过外部变量接收异步逻辑的赋值,一来会有多线程可见性问题,二来不符合函数式编程规范,直接通过
thenApply做结果转换即可。
如果需要给异常场景设置默认返回值,可以用exceptionally统一处理:
String myOutput = CompletableFuture.supplyAsync(() -> callMyRestService(myUrl)) .exceptionally(e -> { logUtil.error("GET", e.toString()); return null; // 可自定义异常时的默认返回对象 }) .thenApply(myResponseWrapper -> myResponseWrapper != null ? myResponseWrapper.getName() : null) .join(); return myOutput;
方案2:异步返回结果(无阻塞)
如果你不想阻塞当前线程,可以调整方法返回值为CompletableFuture<String>,将异步结果向上透传给调用方,由调用方决定后续处理时机:
public CompletableFuture<String> fetchRestResultAsync(String myUrl) { return CompletableFuture.supplyAsync(() -> callMyRestService(myUrl)) .whenComplete((myResponseWrapper, exception) -> { if (exception != null) { logUtil.error("GET", exception.toString()); } }) .thenApply(myResponseWrapper -> myResponseWrapper != null ? myResponseWrapper.getName() : null); }
调用方可以通过whenComplete、thenAccept等方法异步处理结果,全程不会产生线程阻塞。
额外建议
supplyAsync默认使用JDK公共线程池ForkJoinPool.commonPool(),如果你的REST调用属于IO密集型任务,建议自定义线程池提交任务,避免公共线程池被阻塞影响其他业务逻辑。
内容的提问来源于stack exchange,提问作者reiley
相关产品推荐
相关产品推荐

