简体   繁体   English

如何使用 CompletableFuture 并行运行多个服务调用?

[英]How to run multiple service calls in parallel using CompletableFuture?

I am returning following response to the user我正在向用户返回以下回复

class FinalResponseDTO {
    List<Service1ResponseDTO> service1ResponseDTO;
    Long totalCount;
    List<Service2ResponseDTO> service2ResponseDTO;
}

As of now I am making three sequential calls to compute this FinalResponseDTO , each of this call can be run independent of others.到目前为止,我正在进行三个连续调用来计算这个FinalResponseDTO ,每个调用都可以独立于其他调用运行。 I tried making three different CompletableFuture as:我尝试将三种不同的CompletableFuture制作为:

CompletableFuture<List<Service1ResponseDTO> future1 = CompletableFuture.supplyAsync(() -> service1.callMethod1());
CompletableFuture<Long> future2 = CompletableFuture.supplyAsync(() -> service2.callMethod2());
CompletableFuture<Service2ResponseDTO> future3 = CompletableFuture.supplyAsync(() -> service3.callMethod3());

If I do CompletableFuture.allOf(future1, future2, future3).join();如果我做CompletableFuture.allOf(future1, future2, future3).join(); or Should I call CompletableFuture.allOf(future1, future2, future3).get();或者我应该调用CompletableFuture.allOf(future1, future2, future3).get(); ? ? Even If I call either of these join or get then how should I construct FinalResponseDTO from it.即使我调用其中任何一个joinget那么我应该如何从中构造FinalResponseDTO I am new to the Java 8 concurrency features such as CompletableFuture and I am confused, as each return type of each of these future is different, how should I get combined responses of all such futures and then construct my final output?我是 Java 8 并发功能(例如CompletableFuture )的新手,我很困惑,因为每个未来的每个返回类型都不同,我应该如何获得所有这些期货的组合响应,然后构建我的最终 output?

From the Javadocs of CompletableFuture.allOf() :来自CompletableFuture.allOf()的 Javadocs:

Returns a new CompletableFuture that is completed when all of the given CompletableFutures complete.当所有给定的 CompletableFuture 完成时,返回一个新的 CompletableFuture。 If any of the given CompletableFutures complete exceptionally, then the returned CompletableFuture also does so, with a CompletionException holding this exception as its cause.如果任何给定的 CompletableFuture 异常完成,则返回的 CompletableFuture 也会这样做,并且 CompletionException 将此异常作为其原因。 Otherwise, the results, if any, of the given CompletableFutures are not reflected in the returned CompletableFuture, but may be obtained by inspecting them individually .否则,给定 CompletableFuture 的结果(如果有)不会反映在返回的 CompletableFuture 中,但可以通过单独检查它们来获得

So when the combining CompletableFuture completes, you can inspect the values and construct the final response object using a simple constructor by applying a function that constructs the object:因此,当组合 CompletableFuture 完成时,您可以通过应用构造 ZA8CFDE6331BD59EB2AC96F8911C4B6666Z 的 function 来检查值并使用简单的构造函数构造最终响应 object:

CompletableFuture.allOf(future1, future2, future3).thenApply(v -> 
    new FinalResponseDTO(future1.getNow(null), future2.getNow(null), future3.getNow(null))
);

As implied, you should always check the Javadoc for the behavior of methods such as get() vs getNow() .正如暗示的那样,您应该始终检查 Javadoc 以get()getNow()等方法的行为。 I used the latter here in order to avoid exception handling, because the values would be guaranteed to be available after the allOf CompletableFuture is completed normally.我在这里使用后者是为了避免异常处理,因为在allOf CompletableFuture 正常完成后,这些值将保证可用。

    CompletableFuture<List<Service1ResponseDTO> future1 = 
        CompletableFuture.supplyAsync(() -> service1.callMethod1());
    CompletableFuture<Long> future2 = 
        CompletableFuture.supplyAsync(() -> service2.callMethod2());
    CompletableFuture<List<Service2ResponseDTO>> future3 = 
        CompletableFuture.supplyAsync(() -> service3.callMethod3());

    CompletableFuture.allOf(future1, future2, future3).get();

    return new FinalResponseDTO(future1.join(), future2.join(), future3.join());

Note: supplyAsync runs on ForkJoinPool.commonPool() so it would be a good choice to provide your own executor eg Executors.newCachedThreadPool() :注意: supplyAsyncForkJoinPool.commonPool()上运行,因此提供您自己的执行程序是一个不错的选择,例如Executors.newCachedThreadPool()

CompletableFuture.supplyAsync(() -> action, executor);

Instead of using CompletableFuture.allOf , you could fall back to the somewhat hidden Applicative of the CompletableFuture :而不是使用CompletableFuture.allOf ,您可以回退到CompletableFuture有点隐藏的 Applicative :

static <T, R> CompletableFuture<R> alsoApply(CompletableFuture<T> future,     CompletableFuture<Function<T, R>> f) {
    return f.thenCompose(future::thenApply);
}

With this helper function you can execute futures in parallel threads:使用这个助手 function 您可以在并行线程中执行期货:

CompletableFuture<String> future = alsoApply(
    CompletableFuture.supplyAsync(() -> "a"),
    CompletableFuture.supplyAsync(() -> "b")
.thenApply(b -> a -> a + b));

assertEquals("ab", future.get());

See this question and answer for where this is coming from and why and how it works.请参阅此问题和答案,了解它的来源以及它的工作原理和方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM