排版就不做了,我比较懒,直接删除所有文字,贴代码完事,我这里重新编辑一下,并且优化相关代码,本次编辑时间 2023-08-09 13:34,
Controller代码:
@RestController @RequestMapping("thread") public class ThreadTestController { @Resource private ThreadTestService threadTestService; @RequestMapping(value = "batchInsert") public CommonResult addBatchRecord(){ int num = threadTestService.addBatchRecord(); return new CommonResult(num); } }
ServiceImpl代码:
@Service public class ThreadTestServiceImpl implements ThreadTestService { private final Logger logger = LoggerFactory.getLogger(ThreadTestServiceImpl.class); @Resource private SqlSessionTemplate sqlSessionTemplate; @Override public int addBatchRecord() { int num = 0; List<Student> studentList = new ArrayList<>(); Student student; for(int i = 1; i < 1000001; i++){ student = new Student(); student.setId(i); student.setName("学生" + i); student.setAge(20); student.setSex(i % 2 == 0 ? "男" : "女"); student.setStuNo("No." + i); studentList.add(student); } long start = System.currentTimeMillis(); AtomicBoolean rollbackFlag = new AtomicBoolean(false); SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(); Connection connection = sqlSession.getConnection(); try { connection.setAutoCommit(false); //获取mapper StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class); studentMapper.deleteAllRecords(); //分组插入数据 List<List<Student>> partData = Lists.partition(studentList,100000); CountDownLatch countDownLatch = new CountDownLatch(partData.size()); for(List<Student> list : partData){ ThreadPoolUtils.getExecuteThreadPool() .submit(new BatchInsertTask(list, countDownLatch, rollbackFlag, studentMapper)); } countDownLatch.await(); if(rollbackFlag.get()){ logger.info("batchInsert failed"); connection.rollback(); }else{ logger.info("batchInsert success"); connection.commit(); num = 1; } //结束 long end = System.currentTimeMillis(); System.out.println("所用时长: " + (end - start)/1000 + " s"); } catch (Exception e) { logger.error("batchInsert has error, msg: {}", JSON.toJSONString(e)); throw new RuntimeException("执行出错"); } finally { try { connection.close(); } catch (SQLException e) { throw new RuntimeException(e); } } return num; } }
BatchInsertTask 实现代码:
public class BatchInsertTask implements Runnable{ private StudentMapper studentMapper; private List<Student> list; private CountDownLatch countDownLatch; private AtomicBoolean rollbackFlag; public BatchInsertTask(List<Student> list, CountDownLatch countDownLatch, AtomicBoolean rollbackFlag, StudentMapper studentMapper){ this.list = list; this.countDownLatch = countDownLatch; this.rollbackFlag = rollbackFlag; this.studentMapper = studentMapper; } @Override public void run() { //启动执行 发现其他线程已经报错,则直接停止 if(rollbackFlag.get()){ return; } //具体执行逻辑 String threadName = Thread.currentThread().getName(); try { if(CollectionUtils.isEmpty(list)){ return; } //分配的是10w 这里测试做再次分组 一次插入2000条 具体大小自己可以调整 List<List<Student>> partList = Lists.partition(list, 2000); for(List<Student> part : partList){ studentMapper.batchInset(part); } }catch (Exception e){ //执行异常 更改标记状态 rollbackFlag.set(true); }finally { countDownLatch.countDown(); } } }
以上就是我分享的内容,返回值我随便做的,参考时自我调整,如果插入数据异常会回滚,可以放心使用,建议在上生产之前先进行完整测试,如果有帮助到你,请点赞+收藏,谢谢~