多线程事务如何回滚?

news2024/11/14 22:02:59

背景介绍

1,最近有一个大数据量插入的操作入库的业务场景,需要先做一些其他修改操作,然后在执行插入操作,由于插入数据可能会很多,用到多线程去拆分数据并行处理来提高响应时间,如果有一个线程执行失败,则全部回滚。

2,在spring中可以使用@Transactional注解去控制事务,使出现异常时会进行回滚,在多线程中,这个注解则不会生效,如果主线程需要先执行一些修改数据库的操作,当子线程在进行处理出现异常时,主线程修改的数据则不会回滚,导致数据错误。

3,下面用一个简单示例演示多线程事务。

公用的类和方法

/**
 * 平均拆分list方法.
 * @param source
 * @param n
 * @param <T>
 * @return
 */
public static <T> List<List<T>> averageAssign(List<T> source,int n){
    List<List<T>> result=new ArrayList<List<T>>();
    int remaider=source.size()%n; 
    int number=source.size()/n; 
    int offset=0;//偏移量
    for(int i=0;i<n;i++){
        List<T> value=null;
        if(remaider>0){
            value=source.subList(i*number+offset, (i+1)*number+offset+1);
            remaider--;
            offset++;
        }else{
            value=source.subList(i*number+offset, (i+1)*number+offset);
        }
        result.add(value);
    }
    return result;
}
/**  线程池配置
 * @version V1.0
 */
public class ExecutorConfig {
    private static int maxPoolSize = Runtime.getRuntime().availableProcessors();
    private volatile static ExecutorService executorService;
    public static ExecutorService getThreadPool() {
        if (executorService == null){
            synchronized (ExecutorConfig.class){
                if (executorService == null){
                    executorService =  newThreadPool();
                }
            }
        }
        return executorService;
    }

    private static  ExecutorService newThreadPool(){
        int queueSize = 500;
        int corePool = Math.min(5, maxPoolSize);
        return new ThreadPoolExecutor(corePool, maxPoolSize, 10000L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(queueSize),new ThreadPoolExecutor.AbortPolicy());
    }
    private ExecutorConfig(){}
}
/** 获取sqlSession
 * @author 86182
 * @version V1.0
 */
@Component
public class SqlContext {
    @Resource
    private SqlSessionTemplate sqlSessionTemplate;

    public SqlSession getSqlSession(){
        SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();
        return sqlSessionFactory.openSession();
    }

示例事务不成功操作

/**
 * 测试多线程事务.
 * @param employeeDOList
 */
@Override
@Transactional
public void saveThread(List<EmployeeDO> employeeDOList) {
    try {
        //先做删除操作,如果子线程出现异常,此操作不会回滚
        this.getBaseMapper().delete(null);
        //获取线程池
        ExecutorService service = ExecutorConfig.getThreadPool();
        //拆分数据,拆分5份
        List<List<EmployeeDO>> lists=averageAssign(employeeDOList, 5);
        //执行的线程
        Thread []threadArray = new Thread[lists.size()];
        //监控子线程执行完毕,再执行主线程,要不然会导致主线程关闭,子线程也会随着关闭
        CountDownLatch countDownLatch = new CountDownLatch(lists.size());
        AtomicBoolean atomicBoolean = new AtomicBoolean(true);
        for (int i =0;i<lists.size();i++){
            if (i==lists.size()-1){
                atomicBoolean.set(false);
            }
            List<EmployeeDO> list  = lists.get(i);
            threadArray[i] =  new Thread(() -> {
                try {
                 //最后一个线程抛出异常
                    if (!atomicBoolean.get()){
                        throw new ServiceException("001","出现异常");
                    }
                    //批量添加,mybatisPlus中自带的batch方法
                    this.saveBatch(list);
                }finally {
                    countDownLatch.countDown();
                }

            });
        }
        for (int i = 0; i <lists.size(); i++){
            service.execute(threadArray[i]);
        }
        //当子线程执行完毕时,主线程再往下执行
        countDownLatch.await();
        System.out.println("添加完毕");
    }catch (Exception e){
        log.info("error",e);
        throw new ServiceException("002","出现异常");
    }finally {
         connection.close();
     }
}

数据库中存在一条数据:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1420548.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Stable Diffusion web UI 安装、启动脚本、常见问题、插件(linux)

Stable Diffusion本身是一个模型&#xff0c;对于大多数想试试的人来说&#xff0c;使用这个web ui版本最合适 建议先看完再动手&#xff0c;虽然不难但是有门槛&#xff08;主要要解决网络问题&#xff09;&#xff0c;如果深入需要会python 如果只是想试试的&#xff0c;建议…

市面上的小型办公室都是哪些人在租?

市面上的小型办公室&#xff0c;又称服务式办公室&#xff0c;是一种将传统的写字楼进行精装修&#xff0c;分割成若干个独立的小型办公空间&#xff0c;提供给不同的租户的新型办公模式。那么&#xff0c;市面上的小型办公室都是哪些人在租&#xff1f;本文将从租户的特点和需…

Linux服务器配置与管理(第四次实验)

实验目的及具体要求 目的 1.了解网络配置之文件 2.掌握网络常用命令 3.掌握ssh远程连接 任务 1.修改主机名为TX 2.查看系统的网络接口信息 3.在路由表中添加一条路由 4.删除上一步添加的路由 5.查看网络中所有的TCP端口连接信息 6.X SHELL远程链接Centos系统 7.在X …

35岁老兵,从金山被裁员到创业

35岁&#xff0c;对于许多人而言&#xff0c;是事业中一个重要的节点。对我而言&#xff0c;这一年成为了我生命中的转折点。2023年8月份的一个上午&#xff0c;突然被领导叫到小黑屋&#xff0c;告知我被裁员了。起初&#xff0c;这个决定对我来说是一个巨大的打击&#xff0c…

榜单!AR-HUD进入高增速周期,TOP10本土供应商争夺市场

高工智能汽车研究院数据显示&#xff0c;2023年1-9月&#xff0c;中国市场&#xff08;不含进出口&#xff09;乘用车前装标配W/AR HUD交付149.54万辆&#xff0c;同比增长45.86%。 其中&#xff0c;W-HUD仍是主流。而同期&#xff0c;AR-HUD的前装标配搭载量超过10万辆&#x…

Mysql-ReadView + MVCC-RR 与 RC

实验准备 创建脚本 CREATE TABLE user (id int(11) NOT NULL AUTO_INCREMENT,name varchar(16) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,age int(11) NULL DEFAULT NULL,addr varchar(256) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL,PRIMARY …

希尔伯特变换的在信号解调时的示例

1.希尔伯特变换的应用场景 希尔伯特变换&#xff0c;在数学上的含义是清晰的。它是一个数字移相器&#xff0c;可以把通过它的任何一个信号相移-90度。这个数学工具在信号解调时&#xff0c;会有非常有用的特性出现。可以看示例&#xff1a; 解释一下&#xff1a; 1.最上面的…

transformer | transformer的输入部分input coding

文章目录 transformer的输入部分input codingBPEBPE所解决的问题——OOV PE&#xff08;Position Encoding&#xff09;位置编码 transformer的输入部分input coding transformer的输入部分input codingBPEPE BPE BPE是指一种词分类算法。 起初&#xff0c;会将每个单词都拆分…

旧物回收小程序开发:创新与可持续发展的交汇点

随着社会的发展和人们生活水平的提高&#xff0c;物品的更新换代速度越来越快&#xff0c;这导致了大量的旧物被闲置或丢弃。为了解决这个问题&#xff0c;旧物回收成为了重要的环保行动。而随着移动互联网的普及&#xff0c;旧物回收小程序的开发也成为了新的趋势。本文将探讨…

本次安装Visual Studio 所用的安装程序不完整。请重新运行VisualStudio安装程序以解决此问题

今天点开VS的时候遇到了这个问题 因为昨天升级到一半电脑关机了&#xff0c;今天打开软件遇到如下错误&#xff0c; 解决办法很简单&#xff0c;找到安装目录进入Installer文件夹 我的目录在C:\Program Files (x86)\Microsoft Visual Studio\Installer 找到vs_installer.exe…

《HTML 简易速速上手小册》第8章:HTML 表单高级技术(2024 最新版)

文章目录 8.1 数据收集与处理8.1.1 基础知识8.1.2 案例 1&#xff1a;创建一个注册表单8.1.3 案例 2&#xff1a;创建一个调查问卷表单8.1.4 案例 3&#xff1a;创建一个动态添加输入字段的表单 8.2 定制化表单元素8.2.1 基础知识8.2.2 案例 1&#xff1a;创建一个带有定制选择…

打击者H5小游戏

欢迎来到程序小院 打击者 玩法&#xff1a;点击飞机上下左右移动躲过子弹射击&#xff0c;打掉上方敌人飞机&#xff0c; 遇到药包会增加能量&#xff0c;弹药包会升级武器&#xff0c;快去射击吧^^。开始游戏https://www.ormcc.com/play/gameStart/262 html <div id"…

点击查看 Milvus 社区十大关键词(下)

在昨天的文章《点击查看 Milvus 社区十大关键词&#xff08;上&#xff09;》中&#xff0c;我们提到将 2023 年所有 Milvus 技术交流群的聊天历史做了整理分析&#xff0c;得到了如下的一张词云图&#xff1a; 按照热度&#xff0c;排名前十的关键词依次为&#xff1a;版本、查…

游戏缺失d3dcompiler_47.dll怎么办,这五种方法可以帮你解决

d3dcompiler_47.dll文件的缺失可能会导致一系列显著且影响用户体验的问题。作为DirectX 3D编译器的重要组件&#xff0c;该动态链接库文件在许多依赖于高级图形处理的应用程序和游戏运行过程中起着至关重要的作用。当系统中缺少这个特定的dll文件时&#xff0c;可能会出现诸如应…

会话技术复习笔记

一.登录校验的需求 什么是登录校验&#xff1f; 所谓登录校验&#xff0c;指的是我们在服务器端接收到浏览器发送过来的请求之后&#xff0c;首先我们要对请求进行校验。先要校验一下用户登录了没有&#xff0c;如果用户已经登录了&#xff0c;就直接执行对应的业务操作就可以…

H264 编码标准配置档次 Profile 详解

H264 中 Profile 定义&#xff1a; H264 标准中规定了 多种档次Profile&#xff0c; 每种 Profile 都规定了一个算法特征和限制的子集&#xff0c;任何遵守某个 Profile 的解码器都应该支持与其相应的子集。维基百科中解释&#xff1a; The standard defines several sets of …

深度学习之循环神经网络 (基础)

循环神经网络简称为RNN&#xff0c;&#xff08;之前讲到的卷积神经网络简称为CNN&#xff09;。 以前我们在使用全链接网络的时候&#xff0c;我们将这种网络叫做Dense 或者是Deep。 Dense链接指的是全链接的。 我们输入的数据是数据样本的不同特征&#xff1a;x1&#xff…

STM32F407移植OpenHarmony笔记4

上一篇写到make menuconfig报错&#xff0c;继续开整。 make menuconfig需要/device/soc/*下面有对应的Kconfig文件。 直接去gitee下载stm32的配置文件拿来参考用。 先提取Kconfig文件&#xff0c;后面再添加其它文件。https://gitee.com/openharmony/device_soc_st/tree/Open…

ubuntu 22安装配置并好安全加固后,普通用户一直登录不上

现象 ubuntu 22安装配置并好安全加固后&#xff0c;普通用户一直登录不上 排查报错 查看日志/var/log/auth.log发现报错 Jan 30 15:49:57 aiv-O-E-M sshd[62570]: PAM unable to dlopen(pam_tally2.so): /lib/security/pam_tally2.so: cannot open shared object file: No …

Docker最新超详细版教程通俗易懂(基础版)

Docker概述 概念&#xff1a;容器虚拟化技术&#xff0c;系统平滑移植&#xff0c;解决了运⾏环境和配置问题的软件容 器&#xff0c;⽅便做持续集成并有助于整体发布的容器虚拟化技术 意义&#xff1a;Docker的出现使得Docker得以打破过去程序即应⽤的观念&#xff0c;透过…