如何利用CompletableFuture保證批量接口請求結果的順序一致性?

如何利用CompletableFuture保證批量接口請求結果的順序一致性?

高效并發處理批量接口請求:確保結果順序一致

高效率地處理大量數據時,并發調用多個第三方接口能顯著提升效率。然而,簡單的線程并發可能導致返回結果順序錯亂,與原始數據列表對應不上。本文將介紹如何利用Java的CompletableFuture解決這個問題,確保接口調用結果與原始數據順序完全一致。

問題:

假設需要并發調用1000多個第三方接口并處理返回結果。如果使用簡單的for循環啟動多個線程,接口調用的順序無法保證,最終結果的順序與原始數據列表不符。某些示例代碼使用CompletableFuture.runAsync執行異步任務,但忽略了結果的收集和順序的維護。

解決方案:

為了保證結果順序與原始數據列表一致,關鍵在于使用CompletableFuture.supplyAsync代替CompletableFuture.runAsync。supplyAsync方法可以返回一個結果,而runAsync沒有返回值。通過supplyAsync返回每個接口調用的結果,再利用流式處理將結果收集到列表中,即可確保結果順序與原始數據列表一致。

改進后的代碼:

public static void main(String[] args) {     List<String> dataList = new ArrayList<>(); // 原始數據列表     // ... 初始化 dataList ...      ExecutorService executorService = new ThreadPoolExecutor(             //核心線程數             Runtime.getRuntime().availableProcessors(),             //最大線程數             Runtime.getRuntime().availableProcessors() * 2,             //線程存活時間             60L, TimeUnit.SECONDS,             new LinkedBlockingQueue<>(),             new ThreadPoolExecutor.CallerRunsPolicy());      List<CompletableFuture<String>> futures = new ArrayList<>();     for (String data : dataList) {         futures.add(CompletableFuture.supplyAsync(() -> {             logger.info("開始執行異步線程->>" + data);             // 調用接口,傳入 data             // 根據接口返回值判斷 data 是否匹配             // 返回處理后的結果             return processData(data); // 處理數據并返回結果         }, executorService)); // 使用自定義線程池     }      // 所有請求完成后處理邏輯     CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenRun(() -> {         List<String> results = futures.stream()                 .map(CompletableFuture::join)                 .collect(Collectors.toList());         logger.info("線程執行完畢:{}", JSON.toJSONString(results));         // 調用發送短信     }).thenRun(() -> executorService.shutdown()); }  // 處理數據的方法,根據實際情況修改 private static String processData(String data) {     // ...  接口調用和數據處理邏輯 ...     return data + "處理后的結果"; }

通過將每個CompletableFuture的結果存儲在futures列表中,并在最后使用futures.stream().map(CompletableFuture::join).collect(Collectors.toList())收集結果,就保證了結果順序與原始數據列表一致。CompletableFuture::join方法會阻塞直到獲取到CompletableFuture的結果。 這樣就有效解決了原代碼中結果順序錯亂的問題。

? 版權聲明
THE END
喜歡就支持一下吧
點贊8 分享