利用CompletableFuture实现并发效果,测试代码如下:
CopyOnWriteArrayList<Integer> resultList = new CopyOnWriteArrayList<>();
ExecutorService threadPool = Executors.newFixedThreadPool(5);
List<CompletableFuture<Void>> futureList = new ArrayList<>();
System.out.println(System.currentTimeMillis());
for (int i=0;i<5;i++) {
int finalI = i;
futureList.add(CompletableFuture.supplyAsync(() -> {
List<Integer> list = new ArrayList<>();
list.add(finalI);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.printf(e.getMessage());
}
return list;
}, threadPool).thenAccept(resultList::addAll));
}
CompletableFuture<Void>[] array = futureList.toArray(new CompletableFuture[0]);
System.out.println(array.length);
CompletableFuture.allOf(array).join();
System.out.println(System.currentTimeMillis());
System.out.println(resultList);
执行结果如下: 1724722676388 5 1724722677451 [3, 2, 4, 1, 0]
该并发有几个注意点:
- resultList必须是线程安全的list,如果直接使用ArrayList会有线程安全问题,当然也可以使用 Collections.synchronizedList(new ArrayList<>())替代。
- 并发查询后,需要等待所有线程执行完成,join动作是必要的。
对于上述代码运用到实际的in查询操作中,可以参考以下代码:
List<Bean> resultList = Collections.synchronizedList(new ArrayList<>());
if (inIds.size() > 0) {
List<CompletableFuture<Void>> futureList = new ArrayList<>();
List<List<Long>> inIdBatchList =
ListUtils.partition(inIds, 50);
for (List<Long> inIdList : inIdBatchList) {
futureList.add(CompletableFuture.supplyAsync(() -> {
return selectIn(inids);
}, executor).thenAccept(resultList::addAll));
}
CompletableFuture.allOf(futureList.toArray(new CompletableFuture[0])).exceptionally(e -> {
if (e.getCause() instanceof MtException) {
throw new CompletionException(e.getCause().getMessage(), e);
} else {
throw new CompletionException(e);
}
}).join();
}