线程池和CountDownLatch配合使用,大数据量批量多次处理

前言

我们在日常开发的时候经常会使用线程池来分批处理大数据,但是有时候我们需要主线程等待所有的子线程处理完大数据才往下走,那么这个时候我们就需要使用线程池配合CountDownLatch,完成这个需求

代码如下

private void multiThreadHandle(List<User> cachedDataList) {
    //单次分批落库条数
    int subList = 1000;
    //计算执行次数
    int count = cachedDataList.size() % subList > 0 ? (cachedDataList.size() / subList) + 1 : cachedDataList.size() / subList;
    //临时集合
    List<User> tempList;
    // 定义CountDownLatch
    CountDownLatch countDownLatch = new CountDownLatch(cachedDataList.size() / subList);
    for (int i = 0; i < count; i++) {
        //截取集合
        tempList = cachedDataList.stream().skip((long) subList * i).limit(subList).collect(Collectors.toList());
        //多线程执行数据处理
        List<User> finalTempList = tempList;
        // 这里就是线程池,这里会开count个线程去分段处理大集合
        EventManagerExecutor.execute(() -> {
            saveData(finalTempList, countDownLatch);
        });
    }
    try {
    	// 主线程等待
        countDownLatch.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

// 操作数据,并且减countDownLatch
private void saveData(List<User> cachedDataList, CountDownLatch countDownLatch){
	try{
	// 操作数据
	}finally{
		// 在这里进行countDownLatch.countDown(); 减countDownLatch
 		countDownLatch.countDown();
	}

}
// 我的线程池
package com.xiangzheng.gmcmember.util.easyExcel;

import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

/**
 * 
 *
 * @author xusj
 * @date 2021.12.17 23:32
 **/
public class EventManagerExecutor {
    public static ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();

    static {
        executor.setCorePoolSize(20);
        // 配置最大线程数
        executor.setMaxPoolSize(50);
        // 配置缓存队列大小
        executor.setQueueCapacity(100);
        // 空闲线程存活时间
        executor.setKeepAliveSeconds(15);
        executor.setThreadNamePrefix("event-executor-thread-");
        // 线程池对拒绝任务的处理策略:这里采用了CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在execute方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是被没有完成的任务阻塞
        executor.setAwaitTerminationSeconds(60);
        executor.initialize();
    }

    public static void execute(Runnable task) {
        executor.execute(task);
    }
}

随机创建线程

 int rnd = ThreadLocalRandom.current().nextInt(3, 10);
            log.info("随机线程数===》{}", rnd);
            CountDownLatch countDownLatch = new CountDownLatch(rnd);
            for (int i = 0; i < rnd; i++) {
                int finalI = i;
                EventManagerExecutor.execute(() -> {
                    List<MemberImportVO> finalTempList = dataList.stream().filter(item -> Long.parseLong(item.getMemberPhone()) % rnd == finalI).collect(Collectors.toList());
                    saveData(finalTempList, countDownLatch, () -> sysId);
                });
            }
            try {
                countDownLatch.await(1, TimeUnit.MINUTES);

3.总结

这样就使用了countDownLatch去等待子线程全部完成之后,再继续跑主线程

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值