多线程下的事务管理,大多数都讲的很乱,我自己写了一个简单的demo,希望能帮助到大家

排版就不做了,我比较懒,直接删除所有文字,贴代码完事,我这里重新编辑一下,并且优化相关代码,本次编辑时间 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();
        }
    }
}

以上就是我分享的内容,返回值我随便做的,参考时自我调整,如果插入数据异常会回滚,可以放心使用,建议在上生产之前先进行完整测试,如果有帮助到你,请点赞+收藏,谢谢~

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值