@Transactional与多线程

今天发现了一段这样的代码,如下

@Transactional
    public void longlongAfter(){
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(4, 4, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
        threadPoolExecutor.execute(new Thread(){
            @Override
            public void run() {
                System.out.println("子线程...");
                for (int i = 0; i < 2; i++) {
                    User user1 = new User().setUserAge(i).setId(5l);
                    User user2 = new User().setUserAge(i).setId(6l);
                    userMapper.updateById(user1);
                    if (condition){
                        throw new RuntimeException("抛出业务异常");
                    }
                    userMapper.updateById(user2);
                }
            }
        });
    }

我们都知道Transactional 是创建了一个事务,保证方法的原子性,如果使用JDBC的写法就如下

相当于第一个代码块,将线程的创建启动放入了try语句块,但是子线程的运行并不会影响主线程,在thread.start开启子线程后,主线程会仍向下运行,主线程结束子线程并不会结束,所以这里的事务对子线程是没有任何约束力的。

 Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        Statement statement = connection.createStatement();
        try {
            statement.execute("insert into student values(null, '王五', 1)");
            int p = 1 / 0;
            statement.execute("insert into student_log values(null, '添加了个雪人')");
            System.out.println("sql 执行。。。");
            connection.commit();
        } catch (Exception e) {
            System.out.println("抛出异常 回滚");
            connection.rollback();
        }

上面的代码导致的问题
1、原子性被破坏,数据不正确。
2、在出现异常后,因为异常的抛出导致子线程提前结束,后续没有问题的反而没有进行处理

处理方式
如果需要关注线程的返回值,并且保证数据(db)的一致性,主线程则必须等待子线程的结束获取返回值,进行db数据处理,这里可以将循环拆分,开启多个线程同时进行处理,节省时间。就不再写代码了。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多线程环境中使用@Transactional注解可能会导致事务失效。因为@Transactional注解默认只对当前线程的方法调用生效,而不会对其他线程中调用的方法生效。所以在多线程环境中,如果想要保证事务的一致性,需要使用其他手段来处理。 在引用中的示例代码中,使用了ThreadLocal来记录当前线程产生的异常,并在主线程中进行异常捕获和事务的回滚。这种方式通过在子线程中将异常信息保存到ThreadLocal中,然后在主线程中判断是否有异常,并进行相应的回滚操作。这样可以保证在多线程环境中的事务一致性。 而在引用中的示例代码中,虽然使用了事务注解@Transactional,但是由于子线程的运行并不会影响主线程的运行,所以事务对子线程是没有任何约束力的。因此,在多线程环境中,不建议使用@Transactional注解来处理事务。 总结来说,多线程环境下的事务管理需要特殊处理。可以通过使用ThreadLocal来记录异常信息,并在主线程中进行异常捕获和事务的回滚来保证事务的一致性。123 #### 引用[.reference_title] - *1* *3* [@Transactional注解下使用多个线程进行异步操作数据,如果产生异常,事务是否回滚?](https://blog.csdn.net/weixin_42541479/article/details/130528106)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] - *2* [@Transactional多线程](https://blog.csdn.net/weixin_43935720/article/details/114262244)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值