如何为CompletableFuture的orTimeout添加自定义超时异常信息?
为CompletableFuture的超时异常添加自定义信息的简便方法
方案一:Java 9+ 直接使用带异常Supplier的orTimeout重载方法
Java 9及以后的CompletableFuture提供了orTimeout(long timeout, TimeUnit unit, Supplier<Throwable> exceptionSupplier)重载方法,这是实现需求最直接的方式。你可以通过Supplier动态生成包含操作名称、超时时长的异常消息,避免硬编码:
import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; CompletableFuture<ResultType> getSomething() { long timeout = 15; TimeUnit timeUnit = TimeUnit.SECONDS; String operationName = "Something"; return someFuture.orTimeout(timeout, timeUnit, () -> new TimeoutException(String.format("The %s timed-out in %d%s", operationName, timeout, timeUnit.toString().toLowerCase().charAt(0)))); }
当超时发生时,调用get()会抛出包含自定义消息的ExecutionException,其getCause()就是你定义的带详细信息的TimeoutException。
方案二:Java 8 兼容方案
如果仍在使用Java 8(该版本没有带Supplier的orTimeout重载),可以通过completeOnTimeout结合thenApply模拟实现:
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; CompletableFuture<ResultType> getSomething() { long timeout = 15; TimeUnit timeUnit = TimeUnit.SECONDS; String operationName = "Something"; return someFuture.completeOnTimeout(null, timeout, timeUnit) .thenApply(result -> { if (result == null) { throw new CompletionException( new TimeoutException(String.format("The %s timed-out in %d%s", operationName, timeout, timeUnit.toString().toLowerCase().charAt(0)))); } return result; }); }
这个逻辑是让超时后返回null,再通过thenApply判断结果是否为null,若为null则抛出带自定义消息的超时异常(用CompletionException包装,符合CompletableFuture的异常处理规范)。
关键说明
- 两种方案的核心都是在超时触发时生成带上下文信息的
TimeoutException,让异常消息直接包含操作名、超时时长,方便定位问题。 - 使用
String.format拼接消息,避免硬编码内容,后续修改超时时间或操作名称时无需调整字符串,提升代码可维护性。
内容的提问来源于stack exchange,提问作者kan
相关产品推荐
相关产品推荐

