Răsfoiți Sursa

add Cf10 demo:超时与异常链(orTimeout/completeOnTimeout/exceptionallyCompose)

yangyi 1 săptămână în urmă
părinte
comite
b7b2105a7d
1 a modificat fișierele cu 49 adăugiri și 0 ștergeri
  1. 49 0
      src/main/java/space/anyi/Cf10_TimeoutAndException.java

+ 49 - 0
src/main/java/space/anyi/Cf10_TimeoutAndException.java

@@ -0,0 +1,49 @@
+package space.anyi;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+public class Cf10_TimeoutAndException {
+    public static void main(String[] args) throws Exception {
+        // orTimeout: 限时等待,超时后该 future 以 TimeoutException 失败。
+        // 注意:它并不会取消底层任务,慢任务仍会继续执行到最后
+        CompletableFuture<String> slow = CompletableFuture.supplyAsync(() -> {
+            sleep(1500);
+            System.out.println("底层慢任务执行完毕(并未被 orTimeout 取消)");
+            return "慢任务结果";
+        });
+        try {
+            slow.orTimeout(500, TimeUnit.MILLISECONDS).join();
+        } catch (Exception e) {
+            System.out.println("orTimeout 超时失败: " + e.getCause());
+        }
+        sleep(1600);   // 给慢任务一些执行时间,验证 orTimeout 不会中断它
+        System.out.println("此时 slow 状态 -> isDone: " + slow.isDone()
+                + ", isCompletedExceptionally: " + slow.isCompletedExceptionally());
+
+        // completeOnTimeout: 超时就给默认值完成,不抛异常,调用方拿到的就是兜底数据
+        CompletableFuture<String> withDefault = CompletableFuture.supplyAsync(() -> {
+            sleep(1500);
+            return "真实数据";
+        }).completeOnTimeout("超时兜底数据", 500, TimeUnit.MILLISECONDS);
+        System.out.println("completeOnTimeout 结果: " + withDefault.join());
+
+        // exceptionallyCompose: 异常后拼接一个"异步降级任务",结果自动展平
+        // 对照 thenCompose:一个是成功后的异步续接,一个是失败后的异步续接
+        CompletableFuture<String> recovered = CompletableFuture.supplyAsync(Cf10_TimeoutAndException::explode)
+                .exceptionallyCompose(ex -> CompletableFuture.supplyAsync(() -> "降级方案返回的数据"));
+        System.out.println("exceptionallyCompose 降级结果: " + recovered.join());
+    }
+
+    private static String explode() {
+        throw new RuntimeException("主任务失败");
+    }
+
+    private static void sleep(long ms) {
+        try {
+            Thread.sleep(ms);
+        } catch (InterruptedException e) {
+            e.printStackTrace();
+        }
+    }
+}