当前位置: 首页 > news >正文

java 线程池 + 分批次批量插入代码

线程池 + 分批次批量插入代码

import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; /** * 批量导入工具类 * 线程池分批插入 + 安全等待 */ @Component public class UserBatchInsert { @Resource private UserMapper userMapper; // 核心线程数:根据服务器CPU核心数设置(推荐 CPU核心数*2) private static final int CORE_THREAD_NUM = 8; // 线程池拒绝策略:调用者线程执行,保证任务不丢失 private static final RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy(); /** * 线程池分批批量插入 * @param data 总数据集合 * @param batchNum 每批次插入条数(推荐 500~1000) * @throws InterruptedException 中断异常 */ public void batchInsertUser(List<User> data, int batchNum) throws InterruptedException { // 1. 参数校验 if (data == null || data.isEmpty()) { return; } if (batchNum <= 0) { batchNum = 500; // 默认批次 } int totalSize = data.size(); // 计算总批次 int batchCount = (totalSize + batchNum - 1) / batchNum; // 自定义线程池(固定核心线程,拒绝OOM) ThreadPoolExecutor executor = new ThreadPoolExecutor( CORE_THREAD_NUM, CORE_THREAD_NUM, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), HANDLER ); CountDownLatch countDownLatch = new CountDownLatch(batchCount); try { for (int i = 0; i < batchCount; i++) { int start = i * batchNum; int end = Math.min(start + batchNum, totalSize); // 关键:subList 转为新集合,避免并发异常 List<User> subList = new ArrayList<>(data.subList(start, end)); // 提交任务 executor.execute(new InsertTask(subList, countDownLatch)); } // 等待所有批次插入完成 countDownLatch.await(); } finally { // 优雅关闭线程池 executor.shutdown(); if (!executor.awaitTermination(60, TimeUnit.SECONDS)) { executor.shutdownNow(); } } } /** * 静态内部类:插入任务 * 必须加 static,避免外部类引用泄漏 */ static class InsertTask implements Runnable { private final List<User> userList; private final CountDownLatch countDownLatch; public InsertTask(List<User> userList, CountDownLatch countDownLatch) { this.userList = userList; this.countDownLatch = countDownLatch; } @Override public void run() { try { // 执行业务:批量插入 if (userList != null && !userList.isEmpty()) { // 调用MyBatis批量插入 userList.forEach(System.out::println); // userMapper.insertUserList(userList); } } catch (Exception e) { // 捕获异常,避免任务失败导致计数器不执行 e.printStackTrace(); } finally { // 必须放在finally:无论成功/失败,都计数-1 countDownLatch.countDown(); } } } }

Mapper 批量插入接口

import org.apache.ibatis.annotations.Param; import java.util.List; public interface UserMapper { /** * 批量新增用户 */ void insertUserList(@Param("list") List<User> list); }

XML SQL(MyBatis)

<insert id="insertUserList"> INSERT INTO user(id,name,phone) VALUES <foreach collection="list" item="item" separator=","> (#{item.id},#{item.name},#{item.phone}) </foreach> </insert>

使用示例

@Autowired private UserBatchInsert userBatchInsert; public void test() throws InterruptedException { // 模拟10000条数据 List<User> userList = new ArrayList<>(); // 每500条一批,多线程插入 userBatchInsert.batchInsertUser(userList, 500); }

重要生产提醒

  1. 批次大小推荐:500~1000 条 / 批(性能最优)
  2. 事务问题:多线程插入无法共用一个事务,每批次是独立事务
  3. 适用场景:大量数据初始化、导入、同步
http://www.jsqmd.com/news/691869/

相关文章:

  • 国产氧氮氢分析仪哪个牌子好?哪家强?环保新政下的行业标杆靠谱生产厂家推荐:宁波普瑞思 - 品牌推荐大师
  • Java Lambda 表达式详解
  • 告别手机热点!用一根网线搞定树莓派4B(Ubuntu 22.04)与Win11的SSH连接(保姆级避坑)
  • 2026年全国口碑好的靠谱的国内验厂辅导公司推荐,专业服务全解析 - 工业设备
  • KLayout版图设计实战:从零掌握开源EDA工具,轻松设计专业集成电路
  • Qianfan-OCR实战案例:法律文书关键条款高亮+相似案例推荐系统雏形
  • FPGA时序总崩?先检查你的复位信号扇出!一个真实项目的优化复盘
  • 告别数据上传失败:深度调试STM32+ESP8266连接OneNET的AT指令与网络交互
  • AO3镜像站终极指南:快速解锁全球同人创作宝库
  • 高价回收闲置天猫超市卡,这些平台你一定要知道! - 团团收购物卡回收
  • Adobe Photoshop(PS)专业教学手册:从基础操作到实战应用
  • 用Multisim和74192芯片复刻经典:手把手教你搭建篮球24秒违例计时器(附仿真文件)
  • Kuboard实战:在内网离线环境下如何一步步部署v3.x并管理多K8s集群?
  • 特征选择子空间集成方法在机器学习中的应用与实现
  • 别让Agent Executor无限循环!聊聊LangChain智能体的迭代控制与调试技巧
  • 告别盲测!手把手教你用rtwpriv命令行对WiFi 2.4G模块进行精准TX发射测试
  • 全自动自动化测量系统专用降温设备市场深度测评报告(2026版) - 品牌推荐大师1
  • PCIe链路省电的秘密:手把手教你理解EIOS与EIEOS的发送与识别规则
  • 别再只查手册了!用Python脚本自动诊断Modbus故障码(附完整代码)
  • Supergateway与ngrok结合:如何安全地公开本地MCP服务器
  • Seurat版本兼容实战:从v5对象无缝降级到v4的完整指南
  • 28-Java instanceof 关键字
  • S32K3系列MCU的SIUL2模块实战:从GPIO配置到外部中断,一个按键控制LED的完整代码解析
  • Streamlit文件上传与下载:完整解决方案与最佳实践
  • 拒绝枯燥命令行!手把手带你部署 Hashcat 可视化管理面板(全流程图文指南)
  • BrowserMob Proxy HAR文件生成完全教程:捕获完整网络性能数据
  • 世界读书日,贺大亿发起1000天连续阅读挑战
  • Autosar Dcm DSL配置深度解析:从协议优先级到通信延迟,如何用Vector Configurator Pro调优诊断性能
  • God自定义条件开发教程:扩展监控能力的终极方案
  • 从‘邻居发现’到‘即插即用’:深入浅出图解IPv6 SLAAC工作原理与安全考量