CompletableFuture | thenApplyAsync vs thenCompose及其用例

我试图理解CompletableFuture,并遇到了2个方法,然后是ApplyAsync然后是Make。 我试图了解这两者之间的区别。

CompletableFuture completableFuture = CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + " Printing hello"); return "Hello"; }).thenCompose((String s) -> { return CompletableFuture.supplyAsync(() -> { System.out.println(Thread.currentThread().getName() + " Adding abc"); return "abc "+s;}); }).thenApplyAsync((String s) -> { System.out.println(Thread.currentThread().getName() + " Adding world"); return s + " World"; }).thenApplyAsync((String s) -> { System.out.println(Thread.currentThread().getName() + " Adding name"); if (false) { throw new RuntimeException("Oh no exception"); } return s + " player!"; }).handle((String s, Throwable t) -> { System.out.println(s != null ? s : "BLANK"); System.out.println(t != null ? t.getMessage() : "BLANK Exception"); return s != null ? s : t.getMessage(); }); 

我如何将这些方法解释为, thenApplyAsync将在不同的线程中执行提供的函数并返回结果,但在内部它被包装在CompletionStage中。 然后, thenCompose将获得返回对CompletionStage的引用。

那么在什么情况下,我thenComposethenApplyAsync使用thenApplyAsync吗?

通过这个链接,但它正在谈论thenApply ,这有点不同: CompletableFuture | 然后应用vs thenCompose

当您有一个返回CompletionStage的操作时,您将使用thenCompose当您有一个不返回CompletionStage的操作时,您将使用thenCompose 。 – >这是在thenApply vs thenCompose

但是, CompletionStage接口的Async变体具有细微差别和罕见的用例。

让我们考虑这个例子:

 import java.util.concurrent.CompletableFuture; public class Futures { public static void main(String[] args) throws InterruptedException { CompletableFuture c = CompletableFuture.runAsync(() -> { System.out.println("run1: " + Thread.currentThread().getId()); }); c.whenComplete((r, t) -> { System.out.println("I'm completed"); }); c.thenCompose(__ -> { System.out.println("thenCompose1: " + Thread.currentThread().getId()); return CompletableFuture.runAsync(() -> { System.out.println("run2: " + Thread.currentThread().getId()); }); }).thenRunAsync(() -> { System.out.println("RunAsync1: " + Thread.currentThread().getId()); }); Thread.sleep(5000); System.out.println("Finished"); } } 

其中输出如下:

 run1: 11 thenCompose1: 11 run2: 12 I'm completed RunAsync1: 11 Finished 

请注意, thenApplyAsync影响thenApplyAsync的已完成状态的非异步变体相比, thenApplyAsync不会影响原始未来的已完成状态。

用例:

thenCompose

然后,当您有2个需要按顺序执行的异步操作时,可以进行组合:

 static CompletionStage insert(Object database) { throw new UnsupportedOperationException(); } static CompletionStage get(String id) { throw new UnsupportedOperationException(); } public static void main(String[] args) throws InterruptedException { Object db = new Object(); // pretend this connects to a database CompletionStage recordInserted = insert(db).thenCompose(id -> get(id)); } 

您只能在插入记录后检索记录。

thenXXXX方法的Async变体

想象一下,您有一个允许用户注册的应用程序,注册后他们会收到一封确认电子邮件以确认他们的帐户。

如果邮件服务器关闭或者花费很长时间撰写电子邮件或执行其他检查,您不希望用户等待。

然后,您将使用thenApplyAsync来触发发送电子邮件逻辑,因为它对您的系统并不重要。 用户总是可以回去说“给我发送另一封电子邮件”

 static CompletionStage register(String username) { throw new UnsupportedOperationException(); } static void sendConfirmationEmail(String username) { throw new UnsupportedOperationException(); } public static void main(String[] args) throws InterruptedException { register("user").thenAcceptAsync(username -> sendConfirmationEmail(username)); } 

在这里,您的系统将在注册完成时作出响应,但不会等待发送电子邮件,从而提高系统的响应能力。

到目前为止,我发现Async变体的用例很少,但确实存在。