web-dev-qa-db-ja.com

CompletableFutureを使用したSpring @Async

このコードには疑問があります。

@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;
}
14
Eddy

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ロジックのすべて。

19
Dovmo