Spring Boot中线程池使用
说明:在一些场景,如导入数据,批量插入数据库,使用常规方法,需要等待较长时间,而使用线程池可以提高效率。本文介绍如何在Spring Boot中使用线程池来批量插入数据。
搭建环境
首先,创建一个Spring Boot项目,pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.12</version><relativePath/></parent><groupId>com.hezy</groupId><artifactId>thread_pool_demo</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.8</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.6</version></dependency></dependencies>
</project>
写一个插入数据的Mapper方法
import com.hezy.pojo.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;@Mapper
public interface UserMapper {@Insert("insert into i_users (username, password) values (#{user.username}, #{user.password})")void insert(@Param("user") User user);
}
写一个接口,用来插入20万条记录,如下:
import com.hezy.pojo.User;
import com.hezy.service.AsyncService;
import com.hezy.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.ArrayList;@RestController
@RequestMapping("user")
public class UserController {/*** 总记录数*/private final static int SIZE = 40 * 10000;@Autowiredprivate UserService userService;@Autowiredprivate AsyncService asyncService;@GetMapping("insert1")public void insert1() {ArrayList<User> list = new ArrayList<>(SIZE);for (int i = 0; i < SIZE; i++) {User user = new User();user.setUsername("user" + i);user.setPassword("password" + i);list.add(user);}long startTime = System.currentTimeMillis();// 批量插入for (User user : list) {userService.insert(user);}long endTime = System.currentTimeMillis();System.out.println("不用线程池===插入40万条记录耗时:" + ((endTime - startTime) / 1000) + "s");}
}
启动项目,测试一下,看要多长时间……11分钟

使用线程池
Spring Boot有自动注入的线程池(threadPoolTaskExecutor),可以手动设置一些属性,为我们所用。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;@Configuration
@EnableAsync
public class ThreadPoolConfig {@Bean(name = "threadPoolTaskExecutor")public Executor threadPoolTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(20);executor.setMaxPoolSize(40);executor.setQueueCapacity(500);executor.setKeepAliveSeconds(60);executor.setThreadNamePrefix("hezy-");executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());executor.initialize();return executor;}
}
使用线程池来完成上面插入数据的操作,如下:
@GetMapping("insert2")public void insert2() {ArrayList<User> list = new ArrayList<>(SIZE);for (int i = 0; i < SIZE; i++) {User user = new User();user.setUsername("user" + i);user.setPassword("password" + i);list.add(user);}// 将数据分成4000批,每批插入100条List<List<User>> batchList = new ArrayList<>();for (int i = 0; i < list.size(); i += 100) {batchList.add(list.subList(i, i + 100));}long startTime = System.currentTimeMillis();CountDownLatch countDownLatch = new CountDownLatch(batchList.size());// 线程池分批插入for (List<User> batch : batchList) {asyncService.executeAsync(batch, userService, countDownLatch);}try {countDownLatch.await();} catch (InterruptedException e) {throw new RuntimeException(e);}long endTime = System.currentTimeMillis();System.out.println("使用线程池===插入40万条记录耗时:" + ((endTime - startTime) / 1000) + "s");}
AsyncService实现类
import com.hezy.pojo.User;
import com.hezy.service.AsyncService;
import com.hezy.service.UserService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;import java.util.List;
import java.util.concurrent.CountDownLatch;@Service
public class AsyncServiceImpl implements AsyncService {@Async("threadPoolTaskExecutor")@Overridepublic void executeAsync(List<User> batch, UserService userService, CountDownLatch countDownLatch) {try {for (User user : batch) {userService.insert(user);}} finally {countDownLatch.countDown();}}
}
启动,测试,速度提升很明显。如果再改造一下insert()方法,一次插入多条数据,肯定还能更快。

总结
本文介绍如何使用Spring Boot装配的线程池Bean,完成大数据量的批量插入操作,提高程序执行效率。
实例完整代码:https://github.com/HeZhongYing/thread_pool_demo
参考B站UP主(孟哥说Java)视频:https://www.bilibili.com/video/BV18r421F7CQ
相关文章:
Spring Boot中线程池使用
说明:在一些场景,如导入数据,批量插入数据库,使用常规方法,需要等待较长时间,而使用线程池可以提高效率。本文介绍如何在Spring Boot中使用线程池来批量插入数据。 搭建环境 首先,创建一个Spr…...
Python机器学习:自然语言处理、计算机视觉与强化学习
📘 Python机器学习:自然语言处理、计算机视觉与强化学习 目录 ✨ 自然语言处理(NLP) 文本预处理:分词、去停用词词向量与文本分类:使用Word2Vec与BERT 🌆 计算机视觉基础 图像预处理与增强目标…...
Vue2 + ElementUI + axios + VueRouter入门
之前没有pc端开发基础,工作需要使用若依框架进行了一年的前端开发.最近看到一个视频框架一步步集成,感觉颇受启发,在此记录一下学习心得。视频链接:vue2element ui 快速入门 环境搭建和依赖安装 安装nodejs安装Vue Cli使用vue create proje…...
GO网络编程(四):海量用户通信系统2:登录功能核心【重难点】
目录 一、C/S详细通信流程图二、消息类型定义与json标签1. 消息类型定义2. JSON标签3.结构体示例及其 JSON 表示:4.完整代码与使用说明 三、客户端发送消息1. 连接到服务器2. 准备发送消息3. 创建 LoginMes 并序列化4. 将序列化后的数据嵌入消息结构5. 序列化整个 M…...
某项目实战分析代码二
某项目实战分析代码二 此次分析的是protobuf的使用操作流程具体实现 3. 业务数据分析3.1 客户端3.2 服务器端简单案例 此次分析的是protobuf的使用 Protocol Buffer( 简称 Protobuf) 是Google公司内部的混合语言数据标准,它是一种轻便高效的结构化数据存储格式&…...
全面指南:探索并实施解决Windows系统中“mfc140u.dll丢失”的解决方法
当你的电脑出现mfc140u.dll丢失的问题是什么情况呢?mfc140u.dll文件依赖了什么?mfc140u.dll丢失会导致电脑出现什么情况?今天这篇文章就和大家聊聊mfc140u.dll丢失的解决办法。希望能够有效的帮助你解决这问题。 哪些程序依赖mfc140u.dll文件…...
QT学习笔记1(QT和QT creator介绍)
QT学习笔记1(QT和QT creator介绍) Qt 是一个跨平台的应用开发框架,主要用于图形用户界面(GUI)应用的开发,但也支持非GUI程序的开发。Qt 支持多种平台,如Windows、macOS、Linux、iOS和Android&a…...
存储电话号码的数据类型,用 int 还是用 string?
在 Java 编程中,存储电话号码的选择可以通过两种常见方式进行:使用 int 类型或 String 类型。这种选择看似简单,但实际上涉及到 JVM 内部的字节码实现、内存优化、数据表示、以及潜在的可扩展性问题。 Java 基本数据类型与引用数据类型的差异…...
【目标检测】工程机械车辆数据集2690张4类VOC+YOLO格式
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):2694 标注数量(xml文件个数):2694 标注数量(txt文件个数):2694 标注…...
target_link_libraries()
target_link_libraries() 是 CMake 中的一个命令,用于指定目标(如可执行文件或库)所依赖的其他库。其主要作用包括: 链接库:将指定的库链接到目标上,使目标能够调用这些库中的函数和使用其功能。 管理依赖…...
Javascript数组研究09_Array.prototype[Symbol.unscopables]
Symbol.unscopables 是 JavaScript 中一个相对较新的符号(Symbol),用于控制对象属性在 with 语句中的可见性。它主要用于内置对象,如 Array.prototype,以防止某些方法被引入到 with 语句的作用域中,避免潜在…...
SkyWalking 自定义链路追踪
对项目中的业务方法,实现链路追踪,方便我们排查问题 引入依赖 <!‐‐ SkyWalking 工具类 ‐‐> <dependency> <groupId>org.apache.skywalking</groupId> <artifactId>apm‐toolkit‐trace</artifactId> <vers…...
Linux驱动开发(速记版)--设备模型
第八十章 设备模型基本框架-kobject 和 kset 80.1 什么是设备模型 设备模型使Linux内核处理复杂设备更高效。 字符设备驱动适用于简单设备,但对于电源管理和热插拔,不够灵活。 设备模型允许开发人员以高级方式描述硬件及关系,提供API处理设备…...
动手学深度学习(李沐)PyTorch 第 6 章 卷积神经网络
李宏毅-卷积神经网络CNN 如果使用全连接层:第一层的weight就有3*10^7个 观察 1:检测模式不需要整张图像 很多重要的pattern只要看小范围即可 简化1:感受野 根据观察1 可以做第1个简化,卷积神经网络会设定一个区域,…...
新编英语语法教程
新编英语语法教程 1. 新编英语语法教程 (第 6 版) 学生用书1.1. 目录1.2. 电子课件 References A New English Grammar Coursebook 新编英语语法教程 (第 6 版) 学生用书新编英语语法教程 (第 6 版) 教师用书 1. 新编英语语法教程 (第 6 版) 学生用书 https://erp.sflep.cn/…...
Golang 服务器虚拟化应用案例
推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...
Elasticsearch基础_4.ES搜索功能
文章目录 一、搜索辅助功能1.1、指定返回的字段1.2、结果计数1.3、结果分页 二、搜索匹配功能2.1、查询所有文档2.2、term级别查询2.2.1、term查询2.2.2、terms查询2.2.3、range查询2.2.4、exists查询 2.3、布尔查询2.3.1、must,should,must_not2.3.2、f…...
Elasticsearch要点简记
Elasticsearch要点简记 1、ES概述2、基础概念(1)索引、文档、字段(2)映射(3)DSL 3、架构原理4、索引字段的数据类型5、ES的三种分页方式(1)深度分页(fromsize)…...
【通信协议】IIC通信协议详解
IIC(Inter-Integrated Circuit)通信协议,又称为I2C(Inter-Integrated Circuit 2)协议,是一种广泛使用的串行通信协议。它由Philips Semiconductor(现NXP Semiconductors)开发&#x…...
2024年中国科技核心期刊目录(社会科学卷)
2024年中国科技核心期刊目录 (社会科学卷) 序号 期刊代码 期刊名称 1 SC02 JOURNAL OF S…...
Intv_AI_MK11 Android应用集成指南:在移动端调用AI模型服务
Intv_AI_MK11 Android应用集成指南:在移动端调用AI模型服务 1. 移动端AI集成的价值与挑战 想象一下,你的Android应用突然拥有了理解用户意图、自动生成图片描述甚至进行自然对话的能力。这正是Intv_AI_MK11这类云端AI模型能为移动应用带来的变革。但在…...
从MATLAB到C++:手把手教你将鱼眼相机标定结果(Scaramuzza模型)部署到OpenCV项目
从MATLAB到C:手把手教你将鱼眼相机标定结果(Scaramuzza模型)部署到OpenCV项目 鱼眼相机因其超广视角在机器人导航、虚拟现实等领域应用广泛。但MATLAB标定结果如何无缝迁移到C工程环境?本文将彻底解决这个痛点,带您完成…...
PyTorch Subset类实战:自定义数据子集与高效训练技巧
1. PyTorch Subset类基础与应用场景 当你面对一个庞大的数据集时,直接加载全部数据进行训练往往会遇到内存不足、训练速度慢等问题。这时候PyTorch的torch.utils.data.Subset类就能派上大用场。这个类就像是一个智能的数据筛选器,可以让你轻松地从原始数…...
OpenClaw 是基于 Node.js 开发的本地 AI 智能体网关,部署核心是先装 **Node.js ≥ 22**,再用 npm 全局安装并完成配置向导
OpenClaw 是基于 Node.js 开发的本地 AI 智能体网关,部署核心是先装 Node.js ≥ 22,再用 npm 全局安装并完成配置向导。以下是完整部署流程: 一、环境准备(必做) 1. 安装 Node.js 22 OpenClaw 要求 Node.js ≥ 22&…...
OpenClaw替代方案:当Qwen3-4B不可用时降级策略
OpenClaw替代方案:当Qwen3-4B不可用时降级策略 1. 为什么需要降级策略 上周三凌晨3点,我的OpenClaw自动化脚本突然停止了工作。原本定时执行的周报生成任务卡在了模型调用环节——Qwen3-4B服务因网络波动暂时不可用。这次意外让我意识到:依…...
Arcgis林业资源管理实战:从GPS打点到小班成图的完整工作流
ArcGIS林业资源管理实战:从GPS打点到小班成图的完整工作流 林业资源调查是森林经营管理的基石,而GIS技术正在彻底改变传统林业调查的工作模式。记得去年参与某林场资源普查时,我们团队用传统方法完成一个林班调查需要两周,而采用A…...
Z-Image-GGUF惊艳效果:运动模糊、景深虚化、镜头畸变等摄影级效果模拟
Z-Image-GGUF惊艳效果:运动模糊、景深虚化、镜头畸变等摄影级效果模拟 1. 项目简介:当AI学会“拍照” 想象一下,你告诉AI:“给我一张黄昏时分,一个女孩在樱花树下奔跑的照片,要有那种风吹过发丝的动感&am…...
利用快马平台快速构建403 forbidden错误演示原型,直观理解HTTP权限状态
今天在调试一个前端项目时,遇到了403 forbidden错误,突然想到可以做个简单的演示原型来帮助团队新人理解这个常见的HTTP状态码。正好最近在用InsCode(快马)平台做各种小demo,发现它特别适合快速搭建这类教学演示项目。 理解403状态码的核心场…...
SEO优化对网站收录有什么作用
SEO优化对网站收录有什么作用 在当今互联网信息爆炸的时代,网站的收录问题显得尤为重要。SEO优化对于网站的收录有着至关重要的作用,无论是对于新开的网站还是已经运营一段时间的网站,优化都能为其带来更多的流量和潜在客户。SEO优化对网站收…...
IT行业的项目经理考不考PMP证书?我劝你看完这篇在决定!
作为在 IT 圈摸爬滚打 8 年,从后端开发一路转型项目经理、带过 10 大小项目的老学长,最近总被身边技术小伙伴追问:想转 PM,必须考 PMP 吗?没证书就做不好项目管理吗?今天就用过来人的经验,跟大…...
