前言
我们在日常开发的时候经常会使用线程池来分批处理大数据,但是有时候我们需要主线程等待所有的子线程处理完大数据才往下走,那么这个时候我们就需要使用线程池配合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去等待子线程全部完成之后,再继续跑主线程
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/96105.html