在项目中对数据进行批量操作的时候,都会有慢的问题,尤其是针对数据量极大的情况下,下面说一下简单的多线程的优化方式:
步骤如下:
- 获取需要进行批量更新的大集合 A,对大集合进行拆分操作,分成 N 个小集合 A-1 ~ A-N
- 开启线程池,针对集合的大小进行调参,对小集合进行批量更新操作
- 对流程进行控制,控制线程执行顺序
封装List的拆分工具类
/**
* List按指定长度拆分
*
* @param list 要拆分的list
* @param size 拆分的长度
* @param <T> 泛型
* @return
*/
public static <T> List<List<T>> partition(final List<T> list, final int size) {
// 非法处理
if (CollectionUtil.isEmpty(list) || size <= 0) {
return Lists.newArrayList();
}
List<List<T>> result = Lists.newArrayList();
// 迭代器
Iterator<T> it = list.iterator();
// List片段存储器
List<T> subList = null;
while (it.hasNext()) {
if (subList == null) {
subList = new ArrayList<>();
}
T t = it.next();
subList.add(t);
if (subList.size() == size) {
result.add(subList);
subList = null;
}
}
// 补充最后一页
if (subList != null) {
result.add(subList);
}
return result;
}
在业务实现类中开启异步执行任务的线程池:
@Override
public void importAdd(List<ArchivesImportParamDTO> totalList) throws InterruptedException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
log.info(sdf.format(new Date()));
final int[] currentNum = {0};
// 调用list拆分方法 拆分数据
List<List<ArchivesImportParamDTO>> groupList = ToolUtil.partition(totalList, 100);
// 创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(groupList.size());
// 声明线程计数器 记录单个任务的执行次数
CountDownLatch countDownLatch = new CountDownLatch(groupList.size());
// 遍历处理拆分的list数据
for (int i = 0; i < groupList.size(); i++) {
int finalI = i;
executorService.execute(() -> {
// 业务处理部分
List<Archives> list = new ArrayList<>();
List<ArchivesImportParamDTO> importParamDTOList = groupList.get(finalI);
for (ArchivesImportParamDTO importParamDto : importParamDTOList) {
currentNum[0]++;
Archives archives = new Archives();
archives.setContractName(importParamDto.getContractName());
archives.setContractCode(importParamDto.getContractCode());
archives.setBusinessId(UUID.randomUUID().toString().replaceAll("-", ""));
archives.setCreateTime(importParamDto.getCreateTime());
list.add(archives);
this.dao.saveAll(list);
list.clear();
}
countDownLatch.countDown();
});
}
countDownLatch.await();
//关闭线程池
executorService.shutdown();
log.info(sdf.format(new Date()));
}
以上便是运用多线程加List分段处理多数据的批量操作的简单方式,仅供参考!