このコードには疑問があります。
@Async
public CompletableFuture<String> doFoo() {
CompletableFuture<String> fooFuture = new CompletableFuture<>();
try {
String fooResult = longOp();
fooFuture.complete(fooResult);
} catch (Exception e) {
fooFuture.completeExceptionally(e);
}
return fooFuture;
}
問題は、doFooがfooFutureをlongOpが(正しくまたは例外的に)終了した後にのみ返すので、すでに完了したフューチャーを返しているのか、Springが何らかの魔法を実行してから本体を実行する前に戻っているのですか?コードがlongOp()でブロックしている場合、計算がエグゼキューターに供給されていることをどのように表現しますか?
おそらくこれ?その他の方法で?
@Async
public CompletableFuture<String> doFoo() {
CompletableFuture<String> completableFuture = new CompletableFuture<>();
CompletableFuture.runAsync(() -> {
try {
String fooResult = longOp();
completableFuture.complete(fooResult);
} catch (Exception e) {
completableFuture.completeExceptionally(e);
}
});
return completableFuture;
}
Springは実際にカバーの背後ですべての作業を行うため、CompletableFuture
を自分で作成する必要はありません。基本的に、@Async
アノテーションの追加は、ifと同じように、元のメソッドを(アノテーションなしで)呼び出します:
CompletableFuture<User> future = CompletableFuture.runAsync(() -> doFoo());
2番目の質問については、エグゼキュータにフィードするために、@Async
アノテーションの value でexectutor Bean名を指定できます。
@Async("myExecutor")
public CompletableFuture<User> findUser(String usernameString) throws InterruptedException {
User fooResult = longOp(usernameString);
return CompletableFuture.completedFuture(fooResult);
}
上記は基本的に次のようになりますif元のメソッドを呼び出したように:
CompletableFuture<User> future = CompletableFuture.runAsync(() -> doFoo(), myExecutor);
そして、そのメソッドから返されたexceptionally
を使用して行うCompletableFuture
ロジックのすべて。