CompletableFuture异步计算工具类
前言
在平时的业务中,有的业务需要在循环中查询数据库(公司规范禁止在for中调用数据库操作),但有时数据量非常大的时候,可以进行异步分批操作。
代码
一些工具类很多包都有,导入自己熟悉的就行。
import cn.hutool.core.collection.CollectionUtil;
import com.google.common.collect.Lists;
import org.springframework.util.CollectionUtils;
import java.util.List;
import java.util.concurrent.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class CompletableFutureUtils<R, E> {
/*
阿里规范说要自己定义才安全
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
*/
private static int LIMIT = 500;
private Executor executor = new ThreadPoolExecutor(
5, 20,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
/**
* 数据库查询-异步批量操作
* @param list
* @param fun
* @return
*/
public List<R> solveBatch(List<E> list, Function<List<E>, List<R>> fun){
if (CollectionUtils.isEmpty(list)){
return null;
}
List<List<E>> lists = Lists.partition(list, LIMIT);
List<CompletableFuture<List<R>>> collect = lists.stream().map(e ->
CompletableFuture.supplyAsync(() -> fun.apply(e), executor)
).collect(Collectors.toList());
List<List<R>> completableFutureList = collect.stream().map(CompletableFuture::join).collect(Collectors.toList());
List<R> result = completableFutureList.stream().filter(CollectionUtil::isNotEmpty).flatMap(List::stream).collect(Collectors.toList());
return result;
}
/**
* 数据库查询-异步单个操作
* @param list
* @param fun
* @return
*/
public List<R> solve(List<E> list, Function<E, R> fun){
if (CollectionUtils.isEmpty(list)){
return null;
}
List<CompletableFuture<R>> collect = list.stream().map(e ->
CompletableFuture.supplyAsync(() -> fun.apply(e), executor)
).collect(Collectors.toList());
List<R> result = collect.stream().map(CompletableFuture::join).collect(Collectors.toList());
return result;
}
}