多线程事务控制

        有时候业务需求在一个方法中使用多线程来提高处理速度,那么采用多线程后整体事务如何该如何控制呢?

        这里的思路是通过CountDownLatch以及volatile来配置使用。

        CountDownLatch是一个程序计数器,可以用来表示当前有多少个线程。

        volatile来保证共享变量的可见性和一致性:简单理解就是一个共享变量,当被某一个线程更改时,其他线程可以马上获取得到该变量修改后的属性。

        然后来看具体代码实现:

package com.xx.service.resourceCenterMain.analysisInspCase;

import com.xx.mapper.targetLibraryMain.system.BaseSysMapper;
import com.xx.pojo.targetLibraryMain.system.BaseSys;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

@RestController
public class ThreadTransaction {

    // 因为使用了多数据源,因此项目采取了手动数据源配置
    @Qualifier("targetLibraryMainTransactionManager")
    @Autowired
    DataSourceTransactionManager dataSourceTransactionManager;

    // 这里是线程配置类
    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Resource
    private BaseSysMapper baseSysMapper;

    private volatile Boolean flag = true;

    @RequestMapping("/tranMapping")
    public void lala(){
        // 放置线程状态
        List<Boolean> flagList = new ArrayList<>();

        // 子线程计数器(当前创建了两个线程)
        CountDownLatch countDownLatch = new CountDownLatch(2);
        // 主线程计数器(表示当前方法)
        CountDownLatch main = new CountDownLatch(1);

        try{
            threadPoolTaskExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    // 子事务
                    TransactionStatus transaction1 = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
                    try {
                        BaseSys baseSys = new BaseSys();
                        baseSys.setSysCode("11111");
                        // 插入数据
                        baseSysMapper.batchInsertBaseSys(baseSys);

                        //表示当前线程代码是否执行成功,后续会根据该list中的状态决定是否回滚事务
                        flagList.add(true);
                        // 计数器-1
                        countDownLatch.countDown();


                        // 阻塞当前线程,直到main计数器为0
                        main.await();
                        if (flag){
                            //所有线程运行成功 提交事务
                            dataSourceTransactionManager.commit(transaction1);
                        }else{
                            // 有线程未成功运行,回滚事务
                            dataSourceTransactionManager.rollback(transaction1);
                        }
                    } catch (InterruptedException e) {
                        countDownLatch.countDown();
                        dataSourceTransactionManager.rollback(transaction1);
                    }
                }
            });

            // 事务2
            threadPoolTaskExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    // 子事务
                    TransactionStatus transaction2 = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
                    try {
                        BaseSys baseSys = new BaseSys();
                        baseSys.setSysCode("22222");
                        // 插入数据
                        baseSysMapper.batchInsertBaseSys(baseSys);

                        //表示当前线程代码是否执行成功,后续会根据该list中的状态决定是否回滚事务
                        flagList.add(false);
                        // 计数器-1
                        countDownLatch.countDown();


                        // 阻塞当前线程,直到main计数器为0
                        main.await();
                        if (flag){
                            //所有线程运行成功 提交事务
                            dataSourceTransactionManager.commit(transaction2);
                        }else{
                            // 有线程未成功运行,回滚事务
                            dataSourceTransactionManager.rollback(transaction2);
                        }
                    } catch (InterruptedException e) {
                        countDownLatch.countDown();
                        dataSourceTransactionManager.rollback(transaction2);
                    }
                }
            });

            // 阻塞当前方法执行,直到countDownLatch计数器为0
            countDownLatch.await();
            for (Boolean bb : flagList) {
                if (!bb){
                    // 判断所有子线程是否有运行失败的,有的话便通过volatile来通知到所有的子线程回滚事务
                    flag = false;
                    break;
                }
            }
            main.countDown();
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

事务也可以采取以下代码处理:

创建一个事务管理器

@Component
public class TransactionalUntil {

    @Resource
    private DataSourceTransactionManager dataSourceTransactionManager;

    /**
     * 开启事务
     */
    public TransactionStatus begin() {
        TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
        return transaction;
    }

    /**
     * 提交事务
     */
    public void commit(TransactionStatus transactionStatus) {
        dataSourceTransactionManager.commit(transactionStatus);
    }

    /**
     * 回滚事务
     */
    public void rollback(TransactionStatus transactionStatus) {
        dataSourceTransactionManager.rollback(transactionStatus);
    }

}

然后注入该管理器后。直接在代码中采用事务管理器进行操作~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

这个名字还中

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值