JAVA并发实现多条件IN查询

60 阅读1分钟

利用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]

该并发有几个注意点:

  1. resultList必须是线程安全的list,如果直接使用ArrayList会有线程安全问题,当然也可以使用 Collections.synchronizedList(new ArrayList<>())替代。
  2. 并发查询后,需要等待所有线程执行完成,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();
}