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

如何记录CompletableFuture的completeOnTimeout超时完成情况?

解决CompletableFuture超时日志记录问题

直接在completeOnTimeout中用lambda实现超时日志记录是不可行的——因为completeOnTimeout的第一个参数是预定义的结果值,不是延迟执行的回调逻辑,它会在调用该方法时就创建好结果,而非超时触发时才执行日志逻辑。

不过可以通过两种可靠方式实现超时日志记录:

方式一:结合orTimeout与exceptionally(推荐)

用orTimeout替代completeOnTimeout,它会在超时抛出TimeoutException,再通过exceptionally捕获异常并记录日志,同时返回空对象,效果和completeOnTimeout一致:

return CompletableFuture.supplyAsync(() -> {
    try {
        log.info("#####Start sleeping");
        Thread.sleep(9000);
        log.info("#####Finished sleeping");
    } catch (InterruptedException e){
        log.info("#####Interrupted");
    }

    TestEntity reputationEntity = getTestEntity(destination);
    return getTestDTO(destination, accountId, reputationEntity);
})
.orTimeout(asyncTimeoutMls, TimeUnit.MILLISECONDS)
.exceptionally(ex -> {
    if (ex.getCause() instanceof TimeoutException) {
        log.info("##### Future针对destination: {} 超时完成", destination);
    } else {
        log.error("##### Future执行异常", ex);
    }
    return new TestDTO();
});

方式二:给超时结果添加标记(配合后续检查)

如果一定要保留completeOnTimeout,可以给超时生成的TestDTO添加一个超时标记字段,后续组合完成后逐个检查:

1. 给TestDTO增加标记

public class TestDTO {
    private boolean isTimeout = false;
    // 其他字段、getter/setter
    public boolean isTimeout() { return isTimeout; }
    public void setTimeout(boolean timeout) { isTimeout = timeout; }
}

2. 超时返回带标记的对象

return CompletableFuture.supplyAsync(() -> {
    // 原有异步逻辑
    try {
        log.info("#####Start sleeping");
        Thread.sleep(9000);
        log.info("#####Finished sleeping");
    } catch (InterruptedException e){
        log.info("#####Interrupted");
    }

    TestEntity reputationEntity = getTestEntity(destination);
    return getTestDTO(destination, accountId, reputationEntity);
})
.completeOnTimeout(() -> {
    TestDTO timeoutDTO = new TestDTO();
    timeoutDTO.setTimeout(true);
    return timeoutDTO;
}, asyncTimeoutMls, TimeUnit.MILLISECONDS);

3. 组合完成后检查并记录

CompletableFuture.allOf(test1ComletableFuture, test2ComletableFuture).join();

if (test1ComletableFuture.get().isTimeout()) {
    log.info("##### test1 Future超时完成");
}
if (test2ComletableFuture.get().isTimeout()) {
    log.info("##### test2 Future超时完成");
}

内容的提问来源于stack exchange,提问作者neverEugene

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 17:37:26