线程池实现批量插入

该博客探讨了在处理大量数据插入时如何利用并行流和线程池进行优化。通过设置线程池参数,如核心和最大线程数、存活时间和队列容量,实现了100个线程并发执行数据插入操作。为了避免数据丢失,计算了每个线程处理的数据量,并使用`Callable`和`Future`来跟踪每个线程的执行结果。在所有线程执行完毕后,进行了日志记录和线程池关闭操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;

线程池可以用来优化向数据库批量插入数据的性能。以下是一种简单的实现方式: 1. 创建一个线程池线程池的大小根据你的机器性能和数据库负载情况来配置。 2. 将需要插入的数据按照一定的规则划分成多个小批次。 3. 创建一个任务队列,将每个小批次的数据都封装成一个任务,并放入任务队列中。 4. 线程池中的每个线程从任务队列中取出一个任务,执行该任务中的插入操作。 5. 执行完任务后,线程将结果返回给主线程,并继续从任务队列中取出下一个任务执行。 6. 主线程等待所有任务执行完毕后,关闭线程池。 以下是一个简单的Java代码示例: ```java import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class DatabaseInsertThreadPool { private ExecutorService executorService; public DatabaseInsertThreadPool(int poolSize) { executorService = Executors.newFixedThreadPool(poolSize); } public void insertDataToDatabase(Data data) { // 将数据按照一定的规则划分成多个小批次 List<List<Data>> dataBatches = splitDataIntoBatches(data); // 将每个小批次的数据都封装成一个任务,并放入任务队列中 for (List<Data> dataBatch : dataBatches) { executorService.submit(() -> { // 执行该任务中的插入操作 insertDataBatchToDatabase(dataBatch); }); } } public void shutdown() { executorService.shutdown(); } private List<List<Data>> splitDataIntoBatches(Data data) { // 将数据按照一定的规则划分成多个小批次 ... } private void insertDataBatchToDatabase(List<Data> dataBatch) { // 将数据批量插入到数据库中 ... } } ``` 你可以根据自己的具体需求来修改代码。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值