CompletableFuture | 然后应用Async vs thenCompose及其用例

Him*_*waj 2 java java-8 completable-future

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

CompletableFuture<String> 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();
});
Run Code Online (Sandbox Code Playgroud)

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

那么在什么情况下,我会thenCompose用完thenApplyAsync吗?

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

ped*_*mss 6

thenCompose当你有一个返回a的操作,CompletionStage并且thenApply当你有一个不返回的操作时,你会使用CompletionStage.- >这是在thenApply vs thenCompose

然而,界面的Async变体CompletionStage有微妙的差异和罕见的用例.

我们考虑这个例子:

import java.util.concurrent.CompletableFuture;

public class Futures {

    public static void main(String[] args) throws InterruptedException {

        CompletableFuture<Void> 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");
    }
}
Run Code Online (Sandbox Code Playgroud)

哪个输出如下:

run1: 11
thenCompose1: 11
run2: 12
I'm completed
RunAsync1: 11
Finished
Run Code Online (Sandbox Code Playgroud)

请注意,thenApplyAsync与影响完成状态的非异步变量相比,不会影响原始未来的完成状态CompletionStage.

用例:

thenCompose

thenCompose当您有2个需要按顺序执行的异步操作时,您可能会:

static CompletionStage<String> insert(Object database) {
    throw new UnsupportedOperationException();
}

static CompletionStage<Object> 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<Object> recordInserted = insert(db).thenCompose(id -> get(id));
}
Run Code Online (Sandbox Code Playgroud)

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

AsyncthenXXXX方法的变种

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

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

然后,您将thenApplyAsync用于启动发送电子邮件逻辑,因为它对您的系统并不重要.用户总是可以回去说"给我发送另一封电子邮件"

static CompletionStage<String> 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));

}
Run Code Online (Sandbox Code Playgroud)

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

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