1 直接上代碼吧。java版本的。
背景是我有一個需求是用戶注銷。注銷時我需要判斷是否有訂單,結算單等業務。這樣我就需要調用其他業務線的接口。
接口需要調用N個(這里是5個)分別判斷是否允許注銷。
悲觀假設每個接口調用要1s那么5個接口就需要5s以上,並且任何一個不可行則整個判斷將不通過。
這時候就需要用到異步任務並行。 這里采用
CompletableFuture的thenCombine 來實現多個異步任務並行。代碼簡單。將兩個test跑一下就可以看到效果,
異常case是將userId寫成 >100的值。第4個任務將會拋錯。這樣就可以看到整體運行結果。
當然拋錯也可以轉換為自己認識的錯誤方式,由調用方來決定是否繼續往下走。
本文為原創,雖然例子很簡單但是可以解決我的需求。分享出來希望能幫到您,
當然如果您有更好的方式歡迎留言共同探討,我的郵箱 375341227@qq.com 有更好的歡迎共同探討。
2
3 import java.util.concurrent.CompletableFuture;
4 import lombok.extern.slf4j.Slf4j;
5 import org.junit.Test;
6
7 @Slf4j
8 public class SupplyAsyncText {
9
10 @Test
11 public void testSyncLogOff() {
12 int userId = 45;
13 // 同步
14 long begin = System.currentTimeMillis();
15 StringBuilder sb = new StringBuilder();
16 sb.append(canDo1(userId));
17 sb.append(canDo2(userId));
18 sb.append(canDo3(userId));
19 sb.append(canDo4(userId));
20 sb.append(canDo5(userId));
21 long end = System.currentTimeMillis();
22 // 每一個執行1s 同步:結果是執行應該是 > 5s 的
23 log.info("noUseAsync |{}|{} s", sb.toString(), (end - begin) / 1000.0);
24 }
25
26 @Test
27 public void testCanLogOff() {
28 // case 設定:如果 userId > 100 則在某一個環節拋錯
29 int userId = 10;
30 // 異步 每一個執行1s 異步並行:結果是執行應該 < 5s
31 long begin2 = System.currentTimeMillis();
32 String result =
33 CompletableFuture.supplyAsync(() -> canDo1(userId))
34 .thenCombine(CompletableFuture.supplyAsync(() -> canDo2(userId)), (s1, s2) -> s1 + s2)
35 .thenCombine(CompletableFuture.supplyAsync(() -> canDo3(userId)), (s1, s2) -> s1 + s2)
36 .thenCombine(CompletableFuture.supplyAsync(() -> canDo4(userId)), (s1, s2) -> s1 + s2)
37 .thenCombine(CompletableFuture.supplyAsync(() -> canDo5(userId)), (s1, s2) -> s1 + s2)
38 .exceptionally(
39 e -> {
40 log.error("exception: ", e);
41 return e.getMessage();
42 })
43 .join();
44 long end2 = System.currentTimeMillis();
45 log.info("supplyAsync|{}|{} s", result, (end2 - begin2) / 1000.0);
46 }
47
48 private String canDo1(int userId) {
49 try {
50 Thread.sleep(1000);
51 } catch (InterruptedException e) {
52 e.printStackTrace();
53 }
54 return "ok";
55 }
56
57 private String canDo2(int userId) {
58 try {
59 Thread.sleep(1000);
60 } catch (InterruptedException e) {
61 e.printStackTrace();
62 }
63 return "ok";
64 }
65
66 private String canDo3(int userId) {
67 try {
68 Thread.sleep(1000);
69 } catch (InterruptedException e) {
70 e.printStackTrace();
71 }
72 return "ok";
73 }
74
75 private String canDo4(int userId) {
76 try {
77 Thread.sleep(1000);
78 } catch (InterruptedException e) {
79 e.printStackTrace();
80 }
81 if (userId > 100) {
82 throw new RuntimeException(String.format("用戶[%s]還有訂單,不可注銷",userId));
83 }
84 return "ok";
85 }
86
87 private String canDo5(int userId) {
88 try {
89 Thread.sleep(1000);
90 } catch (InterruptedException e) {
91 e.printStackTrace();
92 }
93 return "ok";
94 }
95 }