从零出发

中义传家美,永保万年春

0%

使用CompletableFuture搞定循环取值

使用CompletbaleFuture搞定循环取值

一、先看代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/**
* 使用CompletableFuture完成
* @author fusionshen
* @date 2021年12月25日
* @param lineCode
* @param date
* @return
*/
@Override
public List<InspectItem> getInspectRecordsInSomeday(String lineCode, String date) {
Supplier<List<InspectItem>> getOuterItemInfoTask = () -> hbl4Service.selectInspectItemListByLineCode(lineCode);
List<InspectItem> join = CompletableFuture.supplyAsync(getOuterItemInfoTask).join();
List<CompletableFuture<InspectItem>> collect = join.stream().map(t ->
CompletableFuture.supplyAsync(() -> {
try {
return getRecentDataTask(t, LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return t;
})).collect(Collectors.toList());
// 调用allOf, 需要构造数组结构
CompletableFuture<Void> allFutures = CompletableFuture.allOf(collect.toArray(new CompletableFuture[collect.size()]));
CompletableFuture<List<InspectItem>> listCompletableFuture =
allFutures.thenApply(t -> collect.stream().map(v -> v.join()).collect(Collectors.toList()));
return listCompletableFuture.join();
}

二、无返回值的情况

1
2
3
4
5
6
7
8
9
10
11
List<CompletableFuture<Void>> collect = docUrlList.stream().map(t ->
CompletableFuture.runAsync(() -> {
try {
doInsertDocumentDetail(t, contractId);
} catch (Exception e) {
e.printStackTrace();
}
})).collect(Collectors.toList());
// 调用allOf, 需要构造数组结构
CompletableFuture<Void> allFutures = CompletableFuture.allOf(collect.toArray(new CompletableFuture[collect.size()]));
allFutures.join();

三、退化版FutureTask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/**
* 使用FutureTask计算,可考虑替换成CompletableFuture
*
* @param lineId 管控线Id
* @param procedureCode 工序编码
* @param date 日期,格式"yyyy-MM-hh"
* @return
*/
@Override
public List<InspectItem> getHourlyInspectRecords(String lineId, String procedureCode, String date) {
// 获取管控项信息列表
List<InspectItem> inspectItems = hbl4Service.selectInspectItemList(lineId, procedureCode);
if (inspectItems.isEmpty()) {
throw new IllegalArgumentException("管控线Id和工序编码传入有误");
}
// 并发管控项取监测数据,将数据作为data字段存入
List<InspectItem> resultList = new ArrayList<>();
List<Future<InspectItem>> futures = new ArrayList<>();
ExecutorService executorService = Executors.newCachedThreadPool();
System.out.println("已经提交资源申请");
for (InspectItem inspectItem : inspectItems) {
futures.add(executorService.submit(() -> getHourlyDataTask(inspectItem, LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")))));
}
futures.stream().forEach(f -> {
if (!f.isDone()) {
System.out.printf("资源还没有准备好");
}
try {
resultList.add(f.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
executorService.shutdown();
return resultList;
}

四、总结

  • CompletableFuture是FutureTask的增强版,优先考虑使用前者。
  • 一和二是范式,可直接套用,try-catch中放入需要实现的耗时业务。
  • 面试再被问平常工作中是否用过多线程,YES!!!
至少你看了我一眼,我们彼此分享了笑容:)

欢迎关注我的其它发布渠道