1 直接上代码吧。java版本的。
背景是我有一个需求是用户注销。注销时我需要判断是否有订单,结算单等业务。这样我就需要调用其他业务线的接口。
接口需要调用N个(这里是5个)分别判断是否允许注销。
悲观假设每个接口调用要1s那么5个接口就需要5s以上,并且任何一个不可行则整个判断将不通过。
这时候就需要用到异步任务并行。 这里采用
CompletableFuture的thenCombine 来实现多个异步任务并行。代码简单。将两个test跑一下就可以看到效果,
异常case是将userId写成 >100的值。第4个任务将会抛错。这样就可以看到整体运行结果。
当然抛错也可以转换为自己认识的错误方式,由调用方来决定是否继续往下走。
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 }