|
|
@@ -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();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|