Java 8下如何在CompletableFuture的API调用间添加延迟
实现Java8下CompletableFuture的请求间隔调用
针对你遇到的后端无法同时处理并发请求的问题,在Java8环境下可以通过两种方式实现1秒的调用间隔:
方案一:主线程控制提交间隔(简单直接)
直接通过主线程在提交每个任务(除第一个外)前休眠1秒,确保请求错开提交。这种方式无需额外线程池,代码改动最小:
// 确保stockDetailsList是线程安全的,避免多线程add时出现并发问题 List<StockConversionResponse> stockDetailsList = Collections.synchronizedList(new ArrayList<>()); List<CompletableFuture<Void>> completableFutureList = new ArrayList<>(); boolean isFirstTask = true; for (HbbConnectionDetail connectionDetail : hbbConnectionDetail) { if (!isFirstTask) { try { // 非第一个任务,间隔1秒再提交 Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new RuntimeException("提交任务被中断", e); } } isFirstTask = false; CompletableFuture<Void> future = CompletableFuture .supplyAsync( () -> getStockConversionResponse(connectionDetail, finalTeamLead, finalReceivePmsId), configuration.stockConversionExecutor() ) .thenAccept(stockDetailsList::add); completableFutureList.add(future); } // 等待所有任务完成 CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[0])).get();
方案二:用定时线程池调度任务(不阻塞主线程)
如果不想阻塞主线程,可以用ScheduledExecutorService来调度每个任务,让它们按1秒间隔依次启动:
// 确保stockDetailsList是线程安全的 List<StockConversionResponse> stockDetailsList = Collections.synchronizedList(new ArrayList<>()); List<CompletableFuture<Void>> completableFutureList = new ArrayList<>(); // 创建单线程的定时调度池,复用线程 ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); int taskIndex = 0; for (HbbConnectionDetail connectionDetail : hbbConnectionDetail) { // 第N个任务延迟N*1秒启动,实现间隔1秒的效果 long delayMillis = taskIndex * 1000L; CompletableFuture<StockConversionResponse> supplyFuture = new CompletableFuture<>(); scheduler.schedule(() -> { try { StockConversionResponse response = getStockConversionResponse(connectionDetail, finalTeamLead, finalReceivePmsId); supplyFuture.complete(response); } catch (Exception e) { supplyFuture.completeExceptionally(e); } }, delayMillis, TimeUnit.MILLISECONDS); CompletableFuture<Void> future = supplyFuture.thenAccept(stockDetailsList::add); completableFutureList.add(future); taskIndex++; } // 等待所有任务完成 CompletableFuture.allOf(completableFutureList.toArray(new CompletableFuture[0])).get(); // 关闭调度池 scheduler.shutdown();
注意事项
- 必须保证
stockDetailsList是线程安全的,推荐用Collections.synchronizedList或CopyOnWriteArrayList,避免多线程写入时出现数据异常。 - 两种方案都能实现请求间隔1秒提交,方案一代码更简洁,方案二不会阻塞主线程,可根据实际场景选择。
内容的提问来源于stack exchange,提问作者cmb28
相关产品推荐
相关产品推荐

