在当前的 BatchProcessingService 类中,所有异步任务均通过 CompletableFuture.supplyAsync() 提交,并使用了自定义的 taskExecutor 执行器。但目前 没有实现超时控制,即如果某个任务长时间不完成,也不会中断或返回超时结果。
public void processWithTimeout(BatchRequest request,
Consumer<ProcessResult> callback,
CompletableFuture<ProcessResult> completableFuture) {
CompletableFuture<ProcessResult> future = CompletableFuture.supplyAsync(
() -> businessService.dealBusiness(request), taskExecutor);
// 超时 future
CompletableFuture<ProcessResult> timeoutFuture = CompletableFuture.supplyAsync(() -> {
try {
return future.get(5, TimeUnit.SECONDS); // 等待最多5秒
} catch (TimeoutException e) {
future.cancel(true); // 尝试取消原任务
throw new CompletionException(new Exception("处理超时"));
} catch (Exception e) {
throw new CompletionException(e);
}
}, taskExecutor);
timeoutFuture.whenComplete((result, throwable) -> {
if (throwable != null) {
ProcessResult errorResult = new ProcessResult(
request.getId(),
false,
"处理失败: " + throwable.getMessage(),
null,
0,
(Exception) throwable.getCause()
);
callback.accept(errorResult);
completableFuture.completeExceptionally(throwable);
} else {
callback.accept(result);
completableFuture.complete(result);
}
});
}
- 手动 get(timeout) 控制增加超时处理
输入API的请求参数如下:
[{
"id":"1"
},
{
"id":"2"
},
{
"id":"3"
},
{
"id":"999"
}]
- id为999的数据为超时处理
- 模拟超时的业务代码如下所示:
// 模拟处理逻辑
String id = request.getId();
Integer idInt = Integer.valueOf(id) == null ? 0 : Integer.valueOf(id);
// 模拟超时:当ID为特定值时,延迟较长时间
if (StringUtils.isNoneBlank(id) && idInt == 999) { // 假设999表示需要超时测试
try {
Thread.sleep(10000); // 模拟10秒超时
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return new ProcessResult(
request.getId(),
false,
"处理被中断",
null,
-1,
e
);
}
}
完整代码见上一篇博文