Java并发编程:使用CompletableFuture高效有序处理批量接口请求
高并发访问第三方接口能显著提升数据处理效率,但如果不控制线程执行顺序,最终结果可能与原始数据顺序不符,导致后续处理错误。本文介绍如何利用Java的CompletableFuture在多线程环境下,确保接口请求及结果处理的有序性。
问题:直接使用CompletableFuture.runAsync进行异步调用,由于线程执行顺序不可预测,导致返回结果与原始数据列表顺序不一致。CompletableFuture.allOf仅能保证所有任务完成,无法保证顺序。
解决方案:使用CompletableFuture.supplyAsync,它能返回结果。将每个异步任务的返回结果存储在CompletableFuture
改进后的代码示例:
public static void main(String[] args) { List<String> dataList = new ArrayList<>(); // 原始数据列表 // ... 初始化dataList ... ExecutorService executorService = new ThreadPoolExecutor( 10, // corePoolSize 20, // maximumPoolSize 60L, // keepAliveTime TimeUnit.SECONDS, new LinkedBlockingQueue<>(1024), // workQueue new ThreadPoolExecutor.CallerRunsPolicy() // handler ); List<CompletableFuture<String>> futures = new ArrayList<>(); for (String data : dataList) { futures.add(CompletableFuture.supplyAsync(() -> { logger.info("Processing data: {}", data); // 调用第三方接口,处理data // ... 接口调用及结果处理逻辑 ... return data + " - Processed Result"; // 返回处理结果 }, executorService)); } CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenRun(() -> { List<String> results = futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList()); logger.info("All tasks completed. Results: {}", JSON.toJSONString(results)); // 后续处理结果 }).thenRun(() -> executorService.shutdown()); }
改进后的代码使用CompletableFuture.supplyAsync返回每个接口调用的结果,并存储在futures列表中。CompletableFuture.allOf确保所有任务完成后再处理结果,stream().map(CompletableFuture::join).collect(Collectors.toList())保证结果按原始顺序收集,从而解决了并发导致结果顺序错乱的问题。 代码还使用了自定义线程池,以便更好地控制资源使用。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END