多线程事务控制

内容:多线程批量修改数据,1个线程操作报错,所有线程回滚。例子过于简单,主要靠理解

用到的技术:CountDownLatch计数器、AtomicInteger原子类

1.测试代码Controller

  @Test
    public void updateStudentWithThreadsWcc() {
        //查询总数据
        List<Student> allStudents = studentMapper.getAll();
        // 线程数量
        final Integer threadCount = 2;

        //每个线程处理的数据量
        final Integer dataPartionLength = (allStudents.size() + threadCount - 1) / threadCount;

        // 创建多线程处理任务
        ExecutorService studentThreadPool = Executors.newFixedThreadPool(threadCount);
        CountDownLatch mainLatch = new CountDownLatch(1); // 用于判断主线程是否提交
        CountDownLatch threadLatchs = new CountDownLatch(threadCount);
        StudentTaskError taskStatus = new StudentTaskError(); // 用于判断子线程任务是否有错误
        //用来判断是否全部成功a = b 就是全部成功
        AtomicInteger a = new AtomicInteger(0);
        AtomicInteger b = new AtomicInteger(0);
        for (int i = 0; i < threadCount; i++) {
            // 每个线程处理的数据
            List<Student> threadDatas = allStudents.stream()
                    .skip(i * dataPartionLength).limit(dataPartionLength).collect(Collectors.toList());
            studentThreadPool.execute(() -> {
                studentService.updateStudents(threadDatas, threadLatchs,mainLatch,a,b,taskStatus);
            });
        }
        try {
            // 倒计时锁设置超时时间 30s
            boolean await = threadLatchs.await(600, TimeUnit.SECONDS);
            if (!await) { // 等待超时,事务回滚
                taskStatus.setIsError();
            }
        } catch (Throwable e) {
            e.printStackTrace();
            taskStatus.setIsError();
        }
        mainLatch.countDown(); // 切换到子线程执行
        studentThreadPool.shutdown(); //关闭线程池
        System.out.println("主线程完成");
    }

2.测试代码Service

    void updateStudents(List<Student> students, CountDownLatch threadLatch,CountDownLatch mainLatch, AtomicInteger a,AtomicInteger b,StudentTaskError taskStatus);

2.测试代码impl

    @Autowired
    private DataSourceTransactionManager dataSourceTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

public void updateStudents(List<Student> students, CountDownLatch threadLatch,CountDownLatch mainLatch, AtomicInteger a,AtomicInteger b,StudentTaskError taskStatus) {
        TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
        System.out.println("子线程:" + Thread.currentThread().getName());
        //AtomicInteger a = new AtomicInteger(0);
        try {
            students.forEach(s -> {
                int i1 = a.incrementAndGet();
                log.info("线程名:{}==========================第:{}次===================>s.getId:{}", Thread.currentThread().getName(), i1,s.getId());
                if(s.getId()==50) {
                    int aa = 1/0;
                }
                // 更新教师信息
                String newTeacher = "TNO_" + new Random().nextInt(100);
                s.setTeacher(newTeacher);
                int aaa = studentMapper.update(s);
                if(aaa >0){
                    log.info("线程名:{}==========================第:{}次===================>更新成功", Thread.currentThread().getName(), i1);
                    b.incrementAndGet();
                }
            });
        } catch (Throwable e) {
            log.info("线程名:{}==========================异常了",Thread.currentThread().getName());
            taskStatus.setIsError();
        } finally {
            threadLatch.countDown(); // 切换到主线程执行
        }
        try {
            mainLatch.await();  //等待主线程执行
        } catch (Throwable e) {
            taskStatus.setIsError();
        }
        // 判断是否有错误,如有错误 就回滚事务
   /*     log.info("总任务数:{},成功数:{}",a.get(),b.get());
        if(a.get() !=b.get()){
            //成功数,和任务书不一致 回滚
        }*/
        System.out.println(Thread.currentThread().getName()+"回滚前回滚前回滚前回滚前回滚前回滚前回滚前回滚前回滚前回滚前回滚前回滚前回滚前");
        if (taskStatus.getIsError()) {
            System.out.println(Thread.currentThread().getName()+"回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚回滚");
            dataSourceTransactionManager.rollback(transactionStatus);
        } else {
            dataSourceTransactionManager.commit(transactionStatus);
        }
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值