可完成的未来 | thenApplyAsync 与 thenCompose 及其用例
CompletableFuture | thenApplyAsync vs thenCompose and their use cases
我试图了解 CompletableFuture,遇到了 2 种方法,thenApplyAsync 和 thenCompose。
我想了解这两者之间的区别。
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();
});
我如何将这些方法解释为,thenApplyAsync
将在不同的线程中执行提供的函数并 return 结果,但在内部它被包装在 CompletionStage 中。然而,thenCompose
将获得 return 对 CompletionStage 的引用。
那么在什么情况下,我会用thenCompose
而不是thenApplyAsync
?
经历了这个link,但它在谈论thenApply
,这有点不同:
当您有一个 return 是 CompletionStage
的操作时,您将使用 thenCompose
,当您有一个不是 return 的操作时,您将使用 thenApply
一个CompletionStage
。 -> 这是在
但是 CompletionStage
接口的 Async
变体有细微的差别和罕见的用例。
让我们考虑这个例子:
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");
}
}
输出如下:
run1: 11
thenCompose1: 11
run2: 12
I'm completed
RunAsync1: 11
Finished
请注意,thenApplyAsync
不会影响原始 future 的完成状态,而非异步变体会影响 CompletionStage
的完成状态。
用例:
thenCompose
当您有 2 个需要按顺序执行的异步操作时,您可能 thenCompose
:
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));
}
您只能在插入后检索记录。
Async
thenXXXX
方法的变体
想象一下,您有一个允许用户自行注册的应用程序,注册后他们将收到一封确认电子邮件以确认他们的帐户。
您不希望用户在邮件服务器停机或需要很长时间撰写电子邮件或执行额外检查时一直等待。
然后您将使用 thenApplyAsync
来触发发送电子邮件逻辑,因为它对您的系统并不重要。用户总是可以返回并说 "send me another email"
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));
}
此处您的系统将在注册完成后做出响应,但不会等待电子邮件发送,从而提高系统的响应速度。
到目前为止,我发现的 Async
变体的用例很少,但它们确实存在。
我试图了解 CompletableFuture,遇到了 2 种方法,thenApplyAsync 和 thenCompose。 我想了解这两者之间的区别。
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();
});
我如何将这些方法解释为,thenApplyAsync
将在不同的线程中执行提供的函数并 return 结果,但在内部它被包装在 CompletionStage 中。然而,thenCompose
将获得 return 对 CompletionStage 的引用。
那么在什么情况下,我会用thenCompose
而不是thenApplyAsync
?
经历了这个link,但它在谈论thenApply
,这有点不同:
当您有一个 return 是 CompletionStage
的操作时,您将使用 thenCompose
,当您有一个不是 return 的操作时,您将使用 thenApply
一个CompletionStage
。 -> 这是在
但是 CompletionStage
接口的 Async
变体有细微的差别和罕见的用例。
让我们考虑这个例子:
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");
}
}
输出如下:
run1: 11
thenCompose1: 11
run2: 12
I'm completed
RunAsync1: 11
Finished
请注意,thenApplyAsync
不会影响原始 future 的完成状态,而非异步变体会影响 CompletionStage
的完成状态。
用例:
thenCompose
当您有 2 个需要按顺序执行的异步操作时,您可能 thenCompose
:
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));
}
您只能在插入后检索记录。
Async
thenXXXX
方法的变体
想象一下,您有一个允许用户自行注册的应用程序,注册后他们将收到一封确认电子邮件以确认他们的帐户。
您不希望用户在邮件服务器停机或需要很长时间撰写电子邮件或执行额外检查时一直等待。
然后您将使用 thenApplyAsync
来触发发送电子邮件逻辑,因为它对您的系统并不重要。用户总是可以返回并说 "send me another email"
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));
}
此处您的系统将在注册完成后做出响应,但不会等待电子邮件发送,从而提高系统的响应速度。
到目前为止,我发现的 Async
变体的用例很少,但它们确实存在。