You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 01:46:31