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…...
从汽车到无人机:STM32F4的CAN总线实战,手把手教你搭建双节点通信(附代码)
STM32F4 CAN总线工业级应用实战:从无人机飞控到机器人通信 1. CAN总线技术在现代嵌入式系统中的核心价值 CAN总线(Controller Area Network)自1986年由博世公司开发以来,已成为工业控制领域的黄金标准。这项最初为汽车电子设计的通…...
Solidworks 2018+ 机器人模型避坑指南:用SW2URDF插件导出URDF,再导入Webots R2023a完整流程
SolidWorks 2018机器人模型导入Webots全流程避坑指南 在机器人仿真领域,将SolidWorks设计的机械模型准确导入Webots仿真环境是一个关键但充满挑战的环节。许多工程师和学生在初次尝试这一流程时,往往会在版本兼容性、文件路径、坐标系设置等环节遭遇各种…...
ADI CodeFusion Studio:图形化系统规划与数据溯源重塑嵌入式开发
1. 项目概述:当嵌入式开发遇上“系统规划”与“数据信任”在智能边缘设备爆炸式增长的今天,嵌入式开发者正面临着一个前所未有的“甜蜜的烦恼”。一方面,芯片性能越来越强,多核异构架构成为主流,这让我们能在更小的空间…...
精准定位无版权音乐,快速获取商用授权源,Perplexity音乐搜索避坑全手册,深度拆解7类常见误判场景
更多请点击: https://codechina.net 第一章:Perplexity音乐资源搜索的核心价值与定位 Perplexity 音乐资源搜索并非传统意义上的音频播放器或流媒体平台,而是一个面向开发者、音乐学者与内容创作者的语义化音乐元数据发现引擎。其核心价值在…...
USB-Disk-Ejector:告别“设备正在使用“烦恼,Windows USB安全弹出终极指南
USB-Disk-Ejector:告别"设备正在使用"烦恼,Windows USB安全弹出终极指南 【免费下载链接】USB-Disk-Ejector A program that allows you to quickly remove drives in Windows. It can eject USB disks, Firewire disks and memory cards. It …...
iTop实战指南:3个关键挑战与ITSM平台架构优化策略
iTop实战指南:3个关键挑战与ITSM平台架构优化策略 【免费下载链接】iTop A simple, web based CMDB & IT Service Management tool 项目地址: https://gitcode.com/gh_mirrors/it/iTop 在数字化转型浪潮中,企业IT服务管理面临配置信息分散、…...
3分钟上手Awoo Installer:Switch游戏安装终极指南
3分钟上手Awoo Installer:Switch游戏安装终极指南 【免费下载链接】Awoo-Installer A No-Bullshit NSP, NSZ, XCI, and XCZ Installer for Nintendo Switch 项目地址: https://gitcode.com/gh_mirrors/aw/Awoo-Installer 还在为Switch游戏安装烦恼吗…...
终极指南:用DDrawCompat在现代Windows上完美复活经典游戏
终极指南:用DDrawCompat在现代Windows上完美复活经典游戏 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirrors/dd/DDr…...
从硬件电路深入理解计算机中断机制:8088到现代中断控制器
1. 项目概述:从硬件视角重新认识中断在计算机的世界里,中断(Interrupt)是一个既基础又至关重要的概念。它就像是程序世界里的“紧急呼叫”系统,允许CPU这个“大管家”在埋头处理日常事务(执行主程序&#x…...
如何免费下载中国大学MOOC视频:MoocDownloader完整使用指南
如何免费下载中国大学MOOC视频:MoocDownloader完整使用指南 【免费下载链接】MoocDownloader An MOOC downloader implemented by .NET. 一枚由 .NET 实现的 MOOC 下载器. 项目地址: https://gitcode.com/gh_mirrors/mo/MoocDownloader 你是否曾经因为网络不…...
