Spring的多线程事务

2023-11-19

  • 使用编程式事务手动管理多线程事务的生命周期,通过原子类 + CountDown去控制多线程事务的全局提交或回滚
public class ThreadTransactionUtil {

    // 事务管理
    private DataSourceTransactionManager transactionManager;

    // 多线程执行任务列表
    private final List<Handle> handleList = new ArrayList<>();

    // 隔离级别
    private int isolationLevel = TransactionDefinition.ISOLATION_DEFAULT;

    // 传播行为
    private int propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRED;

    /**
     * 示例
     */
    public static void main(String[] args) {
        Object o = new Object();
        boolean isCommit = ThreadTransactionUtil.builder().add(o::toString).add(o::toString).begin();
    }

    /**
     * 构建
     */
    public static ThreadTransactionUtil builder() {
        ThreadTransactionUtil util = new ThreadTransactionUtil();
        util.transactionManager = SpringUtils.getBean(DataSourceTransactionManager.class);
        // TODO 多数据源
//        util.transactionManager = new DataSourceTransactionManager(ds);
        return util;
    }


    /**
     * 添加事务
     */
    public ThreadTransactionUtil add(Handle s) {
        handleList.add(s);
        return this;
    }

    /**
     * 开始执行 
     */
    public boolean begin() {

        // 线程共享状态
        AtomicBoolean isCommit = new AtomicBoolean(true);

        // 计数器
        CountDownLatch cd = new CountDownLatch(handleList.size());

        // 分配线程执行
        handleList.forEach(l -> CompletableFuture.runAsync(() -> {
            // 开启事务
            TransactionStatus ts = beginTransaction();

            // 执行自定义的逻辑
            try {
                l.handle();
            } catch (Exception e) {
                isCommit.set(false);
                log.error("线程事务出现异常",e);
            }

            // 等待计数器归零,不用await方法是因为如果出现回滚通知就算计数器没有归零也无需占用线程资源了,直接回滚
            cd.countDown();
            while (cd.getCount() > 0 && isCommit.get()) {
                sleep(50);
            }

            // 判断回滚还是提交
            if (isCommit.get()) {
                transactionManager.commit(ts);
            } else {
                transactionManager.rollback(ts);
            }
        }));

        // 等待所有线程执行结束 TODO 超时等待抛出异常测试
        try {
            cd.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
            throw new RuntimeException("多线程事务线程等待出现异常");
        }

        return isCommit.get();
    }


    /* ----------------------------------- setter --------------------------------- */

    public ThreadTransactionUtil isolationLevel(int isolationLevel) {
        this.isolationLevel = isolationLevel;
        return this;
    }

    public ThreadTransactionUtil propagationBehavior(int propagationBehavior) {
        this.propagationBehavior = propagationBehavior;
        return this;
    }


    /* ----------------------------------- private --------------------------------- */

    /**
     * 手动开启一个事务
     */
    private TransactionStatus beginTransaction() {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        // 事物隔离级别
        def.setIsolationLevel(isolationLevel);
        // 事务传播行为
        def.setPropagationBehavior(propagationBehavior);
        // 将拿到的事务加入到事务池并返回
        return transactionManager.getTransaction(def);
    }

    /**
     * sleep
     */
    private void sleep(long mill) {
        try {
            Thread.sleep(mill);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 自定义的lambda
     */
    public interface Handle {
        void handle();
    }
    
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring的多线程事务 的相关文章

随机推荐

  • AD20 如何更改标题栏?Altium Designer20 实用技巧系列教程(二)

    AD20 如何更改标题栏 Altium Designer20 实用技巧系列教程 二 视频地址 https www bilibili com video BV1kf4y117TH
  • C语言程序环境剖析——探究从.c到.exe之路

    程序环境 1 程序的翻译环境和执行环境 2 详解编译 链接 2 1 翻译环境 2 2 编译的三部分 预编译 编译 汇编 2 3链接 3 运行环境 1 程序的翻译环境和执行环境 在ANSI C的任何一种实现中 都存在两个不同的环境 翻译环境
  • JavaWeb —— AJAX

    目录 AJAX 基本介绍 A synchronous JavaScript And XML 多用在 1浏览器搜索联想 2用户注册中离开光标 校验数据的正确性 同步和异步的区别 AJAX快速入门 AJAX 基本介绍 A synchronous
  • Manjaro deepin 睡眠后无法唤醒

    最近尝试换了新的桌面 之前是xfce 使用deepin感觉很棒 也很好看 但是遇到下面一个问题 问题 因为我是双系统 因此经常会来回切win linux 但是发现换了deepin桌面后睡眠无法使用了 经常一睡就凉咯 无法唤醒 经过查找问题
  • Activity的四种启动模式和应用场景

    Activity的四种启动模式和应用场景 简介 通过设置ActivityManifestActivity launchMode可以设置Activity的启动模式 默认情况下 使用启动模式 standard 同时 launchMode可以通过
  • 算法编程6:连续子数组的最大和

    问题描述 输入一个整型数组 数组中的一个或连续多个整数组成一个子数组 求所有子数组的和的最大值 要求时间复杂度为O n 示例 输入 nums 2 1 3 4 1 2 1 5 4 输出 6 解释 连续子数组 4 1 2 1 的和最大 为 6
  • CentOS的Linux系统安装docker

    docker的官方网站教程 https docs docker com engine install centos prerequisites 参照官方教程 安装了 yum install y yum utils 搜索其他教程都安装了 yu
  • 字节流、字节流、转换流、打印流

    字节流 字节流 转换流 打印流 一 字符流 概述 字符流只能操作有文字的文件 纯文本文件 字符流的操作原理 字符输入流 先把字节从文件中读取出来 使用的字节流读的 根据文件的编码集把字节数变为对应的字符 把字符 读到内存中 解码的过程 字符
  • react组件状态同步-状态提升

    假设定义组件TemperatureInputSon import React from react class TemperatureInputSon extends React Component constructor props su
  • Linux安装部署Tomcat服务器

    Tomcat Tomcat 服务器是一个免费的开放源代码的Web 应用服务器 属于轻量级应用服务器 在中小型系统和并发访问用户不是很多的场合下被普遍使用 是开发和调试JSP 程序的首选 对于一个初学者来说 可以这样认为 当在一台机器上配置好
  • 【MATLAB第19期】基于贝叶斯Bayes算法优化CNN-LSTM长短期记忆网络的单列时间序列模型及多输入单输出回归预测模型

    基于贝叶斯Bayes算法优化CNN LSTM长短期记忆网络的单列时间序列模型及多输入单输出回归预测模型 前言 前面在 MATLAB第8期 讲解了基于贝叶斯Bayes算法优化LSTM长短期记忆网络的时间序列预测模型 即单输入数据时间序列预测
  • 从“玩枪”到“玩键盘”,退伍军人到程序员的华丽转型

    前言 我的生活平淡无奇 甚至可以说毫无希望 如果你了解我以前的生活 再看到我现在的境况 一定会惊讶 为什么一个人的变化会如此之大 叛逆 事情要从上学时候说起 我从小就是一个叛逆的孩子 贪玩 不爱学习 喜欢 舞枪弄棒 所以在学校的成绩一直都不
  • win10下安装vivado 2018.3之后ise14.7 的impact 无法使用

    软件版本号 操作系统win10 ise14 7 vivado 2018 3 ise14 7 在win10里面问题总结 1 ise14 7 闪退问题 比较好解决 论坛上比较多的解决方法 2 ise 14 7 windows 10 版本的ise
  • Extjs ToolBar动态更改图标

    使用setIconClass方法 Ext getCmp javaEye setIconClass javaEyeCss 其中 javaEye 是toolbar里的一个图标项 javaEyeCss 是css里定义的一个样式 形如 javaEy
  • PHP实现简易版区块链

  • 通过wireshark抓取telnet登陆密码

    笔者学校有一台设备 ip地址是 192 168 84 10 先打开wireshark捕获无线网卡 使用telnet登陆如图所示 按下回车 笔者这里输入的密码是 A603 现在回到wireshark停止抓包 并且在filter处输入如下的过滤
  • 将uboot,kernel,rootfs下载到开发板上

    1 为什么要下载 所谓下载 也称烧录 部署 1 1 什么是u boot Hi3518EV200 单板的 Bootloader 采用 U boot u boot是一种普遍用于嵌入式系统中的Bootloader Bootloader是在操作系统
  • input type=file 获取选择文件名称、路径方法及input上传按钮美化

    获取文件名 document getElementById upload files 0 name 获取文件路径 document getElementById upload value 页面效果 原生代码
  • Git使用教程总结

    第一篇 SVN VS GIT 转载 https blog csdn net daybreak1209 article details 78216798 svn 集中式 中央版本控制 n个版本 联网 局域网 同步 git 分布式 没有中央的概
  • Spring的多线程事务

    使用编程式事务手动管理多线程事务的生命周期 通过原子类 CountDown去控制多线程事务的全局提交或回滚 public class ThreadTransactionUtil 事务管理 private DataSourceTransact