ループ内のCompletableFuture: すべての応答を収集してエラーを処理する方法 質問する

ループ内のCompletableFuture: すべての応答を収集してエラーを処理する方法 質問する

PUTループ内でリクエストのREST APIを呼び出そうとしています。各呼び出しはですCompletableFuture。各API呼び出しは、型のオブジェクトを返します。RoomTypes.RoomType

  • 応答 (成功応答とエラー応答の両方) を別のリストに収集したいのですが、どうすれば実現できますか? allOf1 つの呼び出しが更新に失敗するとすべての結果が取得されないため、使用できないことは確かです。

  • 各呼び出しのエラー/例外をログに記録するにはどうすればよいですか?


public void sendRequestsAsync(Map<Integer, List> map1) {
    List<CompletableFuture<Void>> completableFutures = new ArrayList<>(); //List to hold all the completable futures
    List<RoomTypes.RoomType> responses = new ArrayList<>(); //List for responses
    ExecutorService yourOwnExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

    for (Map.Entry<Integer, List> entry :map1.entrySet()) { 
        CompletableFuture requestCompletableFuture = CompletableFuture
                .supplyAsync(
                        () -> 
            //API call which returns object of type RoomTypes.RoomType
            updateService.updateRoom(51,33,759,entry.getKey(),
                           new RoomTypes.RoomType(entry.getKey(),map2.get(entry.getKey()),
                                    entry.getValue())),
                    yourOwnExecutor
            )//Supply the task you wanna run, in your case http request
            .thenApply(responses::add);

    completableFutures.add(requestCompletableFuture);
}

ベストアンサー1

allOf()全ての初期futureが完了したときに完了するfutureを取得するには、単にを使用し、その後、 を使って成功と失敗に分割します。Collectors.partitioningBy():

List<CompletableFuture<RoomTypes.RoomType>> completableFutures = new ArrayList<>(); //List to hold all the completable futures
ExecutorService yourOwnExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

for (Map.Entry<Integer, List> entry : map1.entrySet()) {
    CompletableFuture<RoomTypes.RoomType> requestCompletableFuture = CompletableFuture
            .supplyAsync(
                    () ->
                //API call which returns object of type RoomTypes.RoomType
                updateService.updateRoom(51, 33, 759, entry.getKey(),
                        new RoomTypes.RoomType(entry.getKey(), map2.get(entry.getKey()),
                                entry.getValue())),
                    yourOwnExecutor
            );

    completableFutures.add(requestCompletableFuture);
}

CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0]))
        // avoid throwing an exception in the join() call
        .exceptionally(ex -> null)
        .join();
Map<Boolean, List<CompletableFuture<RoomTypes.RoomType>>> result =
        completableFutures.stream()
                .collect(Collectors.partitioningBy(CompletableFuture::isCompletedExceptionally)));

true結果のマップには、失敗した futures のエントリが 1 つと、成功した futures のキーのエントリが 1 つ含まれますfalse。その後、2 つのエントリを調べて、それに応じて動作することができます。

元のコードと比較して、2 つのわずかな変更があることに注意してください。

  • requestCompletableFutureは今CompletableFuture<RoomTypes.RoomType>
  • thenApply(responses::add)リストはresponses削除されました

ログ記録/例外処理に関しては、関連する を追加してrequestCompletableFuture.handle()個別にログ記録しますが、requestCompletableFutureからの結果ではなく を保持しますhandle()

おすすめ記事