如何使用CompletableFuture实现分阶段异步任务执行,并分别控制阶段超时和整体超时?
我有一组异步任务,分为两个阶段:
- **阶段一**(任务a、b):任务a、b可并发异步执行,设置该阶段单独的超时时间。
- **阶段二**(任务c、d):在阶段一成功完成后,任务c、d再并发异步执行,同样设置单独的超时时间。
同时,我还想设置一个整体的超时时间,即**任务abcd整体执行的时间不能超过这个总时长**。
1 个回答
看山,看水,看众生,也看自己。苏嫣然你这个需求明确一点说,就是: - 第一阶段:任务 `a` 和任务 `b` 可以异步执行(并行)。 - 第二阶段:只有 `ab` 全部执行完了,任务 `c` 和任务 `d` 才会异步执行(并行)。 - 超时时间有3个级别: 1. 第一阶段 (`ab`) 自己有一个单独的超时。 2. 第二阶段 (`cd`) 自己也有单独的超时。 3. 整个过程 (`abcd`) 整体还有一个总的超时时间。 你希望一次性精确控制上述三个时间点。 下面我给你**完整的清晰实现**: ### 代码实现(Java): ```java import java.util.concurrent.*; public class CompletableFutureTimeoutControl { static ExecutorService executor = Executors.newFixedThreadPool(4); // 简化任务创建 static Callable<String> task(String name, int seconds) { return () -> { TimeUnit.SECONDS.sleep(seconds); System.out.println(name + "完成"); return name; }; } public static void main(String[] args) { // 超时时间设定(秒) int timeoutAB = 3; // ab阶段最多3秒 int timeoutCD = 4; // cd阶段最多4秒 int timeoutTotal = 6; // abcd整体最多6秒 long startTime = System.currentTimeMillis(); try { // 第一阶段:ab CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> { try { return task("任务A", 2).call(); } catch (Exception e) { throw new RuntimeException(e); } }, executor); CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> { try { return task("任务B", 2).call(); } catch (Exception e) { throw new RuntimeException(e); } }, executor); CompletableFuture<Void> stageAB = CompletableFuture.allOf(futureA, futureB); stageAB.get(timeoutAB, TimeUnit.SECONDS); System.out.println("AB阶段完成"); // 检查整体超时是否还有足够时间执行CD long elapsed = (System.currentTimeMillis() - startTime) / 1000; if (elapsed >= timeoutTotal) { throw new TimeoutException("AB阶段执行完,整体超时已到,无时间执行CD"); } // 第二阶段:cd CompletableFuture<String> futureC = CompletableFuture.supplyAsync(() -> { try { return task("任务C", 2).call(); } catch (Exception e) { throw new RuntimeException(e); } }, executor); CompletableFuture<String> futureD = CompletableFuture.supplyAsync(() -> { try { return task("任务D", 2).call(); } catch (Exception e) { throw new RuntimeException(e); } }, executor); CompletableFuture<Void> stageCD = CompletableFuture.allOf(futureC, futureD); // 计算CD阶段可用超时时间(CD阶段和总体超时取较小者) long remainingForCD = timeoutCD(timeoutCD: timeoutCD, startTime: startTime, elapsed: elapsed, timeoutTotal: timeoutTotal); stageCD.get(remaining, TimeUnit.SECONDS); System.out.println("CD阶段完成"); } catch (TimeoutException e) { System.err.println("超时异常:" + e.getMessage()); } finally { executor.shutdown(); } } private static long timeoutCD(int timeoutCD, long startTime, long elapsed, int timeoutTotal) throws TimeoutException { long remainingTotal = timeoutTotal - elapsed; if (remainingTotal <= 0) { throw new TimeoutException("整体任务超时,无时间执行CD"); } // CD的实际超时为CD阶段超时和整体剩余超时之间的最小值 return Math.min(timeoutCD, remaining); } } ``` ### 核心逻辑解释: - **阶段超时独立控制**: - AB阶段单独设定一个超时时间,超时则直接终止。 - CD阶段同样单独设定超时时间,但不能超过整体剩余超时时间。 - **整体超时控制**: - AB执行完成后,重新计算剩余整体时间。 - CD阶段的最大超时时间要确保不会超出整体剩余时间。 这样你就可以同时设置: - AB阶段独立超时 - CD阶段独立超时 - 整个过程整体超时发布于 2025-03-16 17:01 •IP属地 贵州举报评论收藏
公众号进入网站体验更佳

