UserInfo currentUser = this.getCurrentUser();
if (CollectionUtils.isNotEmpty(examCategoryFeeList)) {
//用并行流处理插入数据基础字段,如果不处理,会包空指针
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(100);
threadPoolTaskExecutor.setMaxPoolSize(100);
threadPoolTaskExecutor.setKeepAliveSeconds(3000);
threadPoolTaskExecutor.setQueueCapacity(500);
// 线程池需要初始化!
threadPoolTaskExecutor.initialize();
int nThreads = 100;
int size = examCategoryFeeList.size();
//每个线程执行的插入行数,如果不加1,会造成数据丢失:1537/100=15就会丢失数据,所以是(15+1)*100
int threadSize = examCategoryFeeList.size() / nThreads + 1;
List<Future<Integer>> futures = new ArrayList<>(nThreads);
// 100个线程
for (int i = 0; i < nThreads; i++) {
//判断线程中分配到需要处理的数据 是否小于总数
if (threadSize * (i + 1) <= size) {
//如果小于总数,直接截取,如果大于总数,会截取报错
final List<ExamCategoryFee> insertList = examCategoryFeeList.subList(threadSize * i, threadSize * (i + 1));
if (CollectionUtils.isNotEmpty(insertList)) {
Callable<Integer> callable = () -> {
examCategoryFeeSrv.saveAll(insertList);
return 1;
};
Future<Integer> submit = threadPoolTaskExecutor.submit(callable);
futures.add(submit);
}
} else {
//如果大于总数,截取到末尾值=size
final List<ExamCategoryFee> insertList = examCategoryFeeList.subList(threadSize * i, size);
if (CollectionUtils.isNotEmpty(insertList)) {
Callable<Integer> callable = () -> {
examCategoryFeeSrv.saveAll(insertList);
return 1;
};
Future<Integer> submit = threadPoolTaskExecutor.submit(callable);
futures.add(submit);
}
break;
}
}
if (CollectionUtils.isNotEmpty(futures)) {
try {
//确保所有线程执行所返回值,也就是所有线程执行结束
for (Future<Integer> future : futures) {
this.logInfo("保存收费归类:future", JSON.toJSONString(future));
Integer integer = future.get();
if (1 != integer) {
this.logError("保存收费归类失败");
}
}
threadPoolTaskExecutor.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
return true;
线程池实现批量插入
最新推荐文章于 2024-09-04 10:11:15 发布
该博客探讨了在处理大量数据插入时如何利用并行流和线程池进行优化。通过设置线程池参数,如核心和最大线程数、存活时间和队列容量,实现了100个线程并发执行数据插入操作。为了避免数据丢失,计算了每个线程处理的数据量,并使用`Callable`和`Future`来跟踪每个线程的执行结果。在所有线程执行完毕后,进行了日志记录和线程池关闭操作。
摘要由CSDN通过智能技术生成