-
2022-03-04 10:33:25
@Slf4j @RequiredArgsConstructor public class MultiThreadTransaction { private final PlatformTransactionManager transactionManager; private void asyncSaveBatch() { // 线程个数 final int SIZE = 6; // 交给单个线程处理,失败则加1 final AtomicInteger failedCounter = new AtomicInteger(); final CountDownLatch latch = new CountDownLatch(SIZE); final ExecutorService pool = Executors.newFixedThreadPool(SIZE); List<TransactionStatus> transactionStatuses = Collections.synchronizedList(new ArrayList<TransactionStatus>()); long beginTime = System.currentTimeMillis(); for (int i = 0; i < SIZE; i++) { pool.execute(() -> { final boolean success = Math.random() > 0.1; log.info(Thread.currentThread().getName() + ", success = " + success); // 将每个线程中的事务状态存入集合单当中 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); // 事物隔离级别,开启新事务,这样会比较安全些。 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 获得事务状态 TransactionStatus status = transactionManager.getTransaction(def); transactionStatuses.add(status); try { /* 插入数据 */ } catch (Exception e) { failedCounter.getAndIncrement(); } finally { transactionManager.commit(status); } latch.countDown(); }); } try { latch.await(); if (failedCounter.get() > 0) { for (TransactionStatus transactionStatus : transactionStatuses) { transactionStatus.setRollbackOnly(); } log.info("执行了回滚过程,回滚事物数据集合大小" + transactionStatuses.size()); } long endTime = System.currentTimeMillis(); log.info("执行批量插入数据耗时" + (int) ((endTime - beginTime)) / 1000 + "秒"); } catch (InterruptedException e) { e.printStackTrace(); } } }
更多相关内容 -
Springboot多线程事务回滚(改良版)
2022-02-23 17:10:06// 如果其他线程已经报错 就停止线程 35 } 36 // 设置一个事务 37 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 38 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_...https://www.cnblogs.com/a5513633/p/13969222.html
/** 2 * 带回滚的异步任务回调 3 * 基类 4 * @author Administrator 5 * 6 */ 7 public abstract class BaseCallBack implements Callable<String> { 8 9 private static Logger logger = LoggerFactory.getLogger(BaseCallBack.class); 10 /** 11 * 需要回滚计数器 12 */ 13 protected CountDownLatch rollBackLatch; 14 /** 15 * 主线程等待计数器 16 */ 17 protected CountDownLatch mainThreadLatch; 18 /** 19 * 是否需要回滚 20 */ 21 protected AtomicBoolean rollbackFlag; 22 /** 23 * 事务 24 */ 25 protected PlatformTransactionManager transactionManager; 26 27 protected abstract void doWork(); 28 29 @Override 30 public String call() throws Exception { 31 if (rollbackFlag.get()) { 32 logger.info("需要回滚,直接不用执行了"); 33 mainThreadLatch.countDown(); 34 return Constant.ERROR_STR; // 如果其他线程已经报错 就停止线程 35 } 36 // 设置一个事务 37 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 38 def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。 39 TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态 40 try { 41 logger.info("业务开始处理:{}", this.getClass().getName()); 42 this.doWork(); 43 logger.info("业务处理结束:{}", this.getClass().getName()); 44 // 业务处理结束 45 mainThreadLatch.countDown(); 46 logger.info("线程内正常 mainThreadLatch.countDown();"); 47 rollBackLatch.await();// 线程等待 48 if (rollbackFlag.get()) { 49 logger.info("回滚事务:{}", this.getClass().getName()); 50 transactionManager.rollback(status); 51 } else { 52 logger.info("提交事务:{}", this.getClass().getName()); 53 transactionManager.commit(status); 54 } 55 return Constant.SAVE_SUCCESS; 56 } catch (Exception e) { 57 e.printStackTrace(); 58 // 如果出错了 就放开锁 让别的线程进入提交/回滚 本线程进行回滚 59 rollbackFlag.set(true); 60 transactionManager.rollback(status); 61 rollBackLatch.countDown(); 62 mainThreadLatch.countDown(); 63 logger.info("线程内异常 mainThreadLatch.countDown();"); 64 return "操作失败:" + e.getMessage(); 65 } 66 } 67 68 public CountDownLatch getRollBackLatch() { 69 return rollBackLatch; 70 } 71 72 public void setRollBackLatch(CountDownLatch rollBackLatch) { 73 this.rollBackLatch = rollBackLatch; 74 } 75 76 public CountDownLatch getMainThreadLatch() { 77 return mainThreadLatch; 78 } 79 80 public void setMainThreadLatch(CountDownLatch mainThreadLatch) { 81 this.mainThreadLatch = mainThreadLatch; 82 } 83 84 public AtomicBoolean getRollbackFlag() { 85 return rollbackFlag; 86 } 87 88 public void setRollbackFlag(AtomicBoolean rollbackFlag) { 89 this.rollbackFlag = rollbackFlag; 90 } 91 92 public PlatformTransactionManager getTransactionManager() { 93 return transactionManager; 94 } 95 96 public void setTransactionManager(PlatformTransactionManager transactionManager) { 97 this.transactionManager = transactionManager; 98 } 99 100 } 复制代码
-
spring boot注解事务+多线程
2019-01-25 13:59:12spring boot 纯注解方法事务控制回滚,注解+简单配置文件使用多线程demo -
SpringBoot事务使用及回滚实现代码详解
2020-08-18 16:49:59主要介绍了SpringBoot事务使用及回滚实现代码详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 -
SpringBoot 多线程下事务处理
2021-01-22 14:49:22Springboot 在多线程下,处理事务; 目前很多开发的小伙伴们,都开始采用Springboot了,因为给我们带来了许多的开发便利,只需要我们关注编写逻辑代码。在工作中是会有很多小伙伴在项目逐步实用到多线程、线程池等...Springboot 在多线程下,处理事务;
目前很多开发的小伙伴们,都开始采用Springboot了,因为给我们带来了许多的开发便利,只需要我们关注编写逻辑代码。在工作中是会有很多小伙伴在项目逐步实用到多线程、线程池等相关技术,但是在使用多线程会出各种各样的问题;事务就是其中一种相对麻烦的事情; 大家都知道Springboot 只需要使用注解标签@Transactional 就可以使用事务了;但是往往在多线程下该处理事务的办法就失效,毫无效果;那又该如何呢? 首先大家都知道控制事务有两种方式;第一种就是刚才所说的注解式事务、第二种就是编程式事务;既然第一种失效那么我们就使用第二种方式来实现嘛;废话不多说,上代码!
package com.slsp.cloud.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.slsp.cloud.bean.User; import com.slsp.cloud.service.UserService; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.math.RandomUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Date; import java.util.HashSet; import java.util.Set; import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 项目初始化加载 */ @Component @Slf4j public class TradeApplicationRunner implements ApplicationRunner { @Autowired private TransactionTemplate transactionTemplate; @Autowired private UserService userService; /** * 模拟多线程下事务处理 * @param args * @throws Exception */ @Override public void run(ApplicationArguments args) throws Exception { //线程池 ExecutorService cachedThreadPool = Executors.newFixedThreadPool(5); for(int i=0;i<1;i++) { cachedThreadPool.execute(new Runnable() { @SneakyThrows public void run() { log.info("多线程执行;"); //开启编程式事务; transactionTemplate.execute(new TransactionCallback<Boolean>() { @Override public Boolean doInTransaction(TransactionStatus transactionStatus) { try { User usr = new User(); //随机名字 String name = UUID.randomUUID().toString().replace("-", ""); System.out.println(name); usr.setUserName(name); usr.setSex(1); //插入数据库 userService.save(usr); //模拟报错; int i=10/0; String name2 = UUID.randomUUID().toString().replace("-", ""); System.out.println(name2); User usr2 = new User(); usr2.setUserName(name2); usr2.setSex(1); userService.save(usr2); return true; } catch (Exception e) { //事务回滚; transactionStatus.setRollbackOnly(); e.printStackTrace(); return false; } } }); } }); } } }
打完收工;简单方便;
-
Spring-Boot中如何使用多线程处理任务方法
2020-08-26 10:23:34主要介绍了Spring-Boot中如何使用多线程处理任务方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
springboot控制多线程事务
2021-05-18 15:10:06import org.springframework.stereotype.Service; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Resource; import java.util.... } } 注意该种方式未经过太多测试import org.springframework.stereotype.Service; import org.springframework.transaction.support.TransactionTemplate; import javax.annotation.Resource; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; @Service public class ThreadTest { @Resource private TransactionTemplate transactionTemplate; @Resource private TestMapper testMapper; public void test1() { final CountDownLatch al = new CountDownLatch(3); final AtomicBoolean ab = new AtomicBoolean(false); CompletableFuture.runAsync(() -> { transactionTemplate.execute((var e) -> { try { TestDto testDto = new TestDto(); testDto.setName("测试线程1"); testMapper.add(testDto); al.countDown(); al.await(); if (ab.get()) throw new RuntimeException("手动抛错"); } catch (Exception exception) { //事务回滚; e.setRollbackOnly(); exception.printStackTrace(); al.countDown(); ab.set(true); return false; } return true; }); }); CompletableFuture.runAsync(() -> { transactionTemplate.execute((var e) -> { try { TestDto testDto = new TestDto(); testDto.setName("测试线程2"); testMapper.add(testDto); al.countDown(); al.await(); if (ab.get()) throw new RuntimeException("手动抛错"); } catch (Exception exception) { //事务回滚; e.setRollbackOnly(); exception.printStackTrace(); al.countDown(); ab.set(true); return false; } return true; }); }); transactionTemplate.execute((var e) -> { try { TestDto testDto = new TestDto(); testDto.setName("测试主线程"); testMapper.add(testDto); al.countDown(); al.await(); if (ab.get()) throw new RuntimeException("手动抛错"); } catch (Exception exception) { //事务回滚; e.setRollbackOnly(); exception.printStackTrace(); al.countDown(); ab.set(true); return false; } return true; }); } }
注意该种方式未经过太多测试
-
详解Spring-Boot中如何使用多线程处理任务
2020-08-31 01:35:19本篇文章主要介绍了详解Spring-Boot中如何使用多线程处理任务,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。 -
SpringBoot多线程事务回滚
2021-03-16 16:42:3112 //主线程业务执行完毕 如果其他线程也执行完毕 且没有报异常 正在阻塞状态中 唤醒其他线程 提交所有的事务13 //如果其他线程或者主线程报错 则不会进入if 会触发回滚 14 if (!rollbackFlag.get()) {15 try{16 ... -
springboot Async 多线程事务失效
2020-01-03 17:48:44异步方法和事务处理方法不能写在一个service类里 -
springboot实现基于多线程@Async的事务统一管理
2022-04-02 14:54:12前言 随着业务的不断深入,总有一些接口需要操作数据库中的很多表,前阵子公司的一个...一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。 用给定的计数 初始化 CountDownL. -
多线程-springboot实现多线程处理任务
2021-01-06 11:16:302.springboot实现多线程 1.在入口类上开启多线程 @SpringBootApplication //@EnableScheduling @EnableAsync public class SampleController { public static void main(String[] args) throws Exception { ... -
springboot多数据源即分布式事务解决方案,添加对多线程的支持
2018-10-17 13:33:52实现系统对多数据源的操作。 实现系统对多数据源的分布式事务管理,包括事务的提交和回滚。 -
SpringBoot使用多线程处理任务
2022-03-18 14:11:24SpringBoot使用多线程处理任务 -
SpringBoot多线程一个事务
2020-04-29 12:08:22最近工作中遇到了一个问题 由于某个批量功能执行时间实在太慢 于是想着使用多线程的方法加速 但是运行了之后发现 他们不存在于一个事务中,想要一个报错 全体回滚暂时不明白该怎么实现 相关伪代码 @Transactional ... -
springboot+多线程
2020-06-22 15:12:07在springboot的过程中,我们会使用到多线程去同时执行某个任务,那么我们就需要多线程,在以前的java中是自己去实现Thread或者runnable来实现多线程,springboot中已经自己拥有了多线程的注解@Async,那么我们现在... -
SpringBoot事务失效
2021-08-30 16:40:57@Transactional 应用在非 public 修饰...TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。 TransactionDefinition.PROPAGATION_NOT_SUPPO. -
SpringBoot执行多线程
2021-09-28 10:52:441.新建配置类,配置线程池 @Configuration @EnableAsync public class ThreadPoolConfiguration { @Bean("ThreadPools") public Executor doSomethingExecutor() {... // 核心线程数,线程池创建时候初始化的线程数 -
springBoot多线程相关原理分析学习记录和使用——<1>
2020-07-29 18:23:28一、springBoot集成多线程 1.1 快速集成方法一 -------------------------方法一:创建AsyncConfig类并实现AsyncConfigurer类,重写方法------------------------------ import org.springframework.aop.... -
SpringBoot事务失效场景
2022-01-02 20:44:12如果我们在开发过程中,把有事务的方法定义了错误的权限,就会导致事务功能出错。众所周知,spring要求被代理的方法必须是public的。说白了,在AbstrctFallbackTransactionAttributedSource类的... -
springboot手动事务回滚的实现代码
2020-08-18 17:59:20主要介绍了springboot手动事务回滚的实现方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 -
【基础】Springboot处理事务@Transactional
2022-06-30 11:19:29【事务】Springboot处理事务@Transactional -
项目开发之Spring多线程事务如何一起提交一起回滚(附代码),并发处理批量数据,实现多线程事务回滚,事务...
2020-11-16 18:58:15目录 ...@SpringBootTest @RunWith(SpringRunner.class) public class PlantTest { @Autowired private PlantService plantService; @Autowired private TransactionThreadPoolExecutor execut -
springboot项目中多线程应用,异步处理,异步调用
2022-04-11 23:21:30springboot项目中多线程应用,异步处理,异步调用 多线程的应用 线程池的应用 异步处理 异步调用 随着开发经验的积累,我们逐渐都了解到了项目中需要多线程的应用或者线程池的应用,有一些耗时的业务需要我们去进行... -
spring 多线程事务的问题
2017-08-09 16:53:41在被spring声明式事务管理的方法内开启多线程,多线程内的方法不被事务控制。 如下代码,线程内调用insert方法,spring不会把insert方法加入事务 就算在insert方法上加入@Transactional注解,也不起作用。 J -
SpringBoot 多任务并行+线程池处理的实现
2020-08-27 16:14:03主要介绍了SpringBoot 多任务并行+线程池处理的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 -
SpringBoot多数据源事务解决方案
2022-05-01 14:06:19之前有文章提供了springboot多数据源动态注册切换的整合方案,在后续使用过程中,发现在事务控制中有多种bug发生,决定对此问题进行分析与解决 前情提要 多数据源切换流程结构图如下所示,包含几个组成元素 自定义... -
@Transactional(事务讲解)和springboot 整合事务
2020-03-06 21:12:39事务在编程中分为两种:声明式事务处理和编程式事务处理 **编程式事务处理:**编码方式实现事务管理,常与模版类TransactionTemplate(推荐使用) 在业务代码中实现事务。 可知编程式事务每次实现都要单独实现,但... -
springboot添加多数据源并实现事务一致性
2022-04-13 15:12:30事务一致性一定要你的数据库引擎支持,我用的数据库是mysql,常见两种搜索引擎,MyISAM和InnoDb,关于它们的区别,网上很多人罗列了,我这里最重要的就是InnoDb支持事务,MyISAM不支持事务。在mysql里面,可以单独为每... -
利用 Spring 实现多线程 + 事务回滚
2022-04-02 00:24:34????推荐大家关注一个公众号????...每日英文You never know how strong you really are until being strong is the only ...不到没有退路之时,你永远不会知道自己有多强大。每日掏心话人在不同的阶段,会有不同的...
收藏数
23,034
精华内容
9,213