多线程和List分段解决批量添加或更新慢的问题

在项目中对数据进行批量操作的时候,都会有慢的问题,尤其是针对数据量极大的情况下,下面说一下简单的多线程的优化方式:

步骤如下:

  • 获取需要进行批量更新的大集合 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分段处理多数据的批量操作的简单方式,仅供参考!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值