当前位置:网站首页>Multi-threading scheme to ensure that a single thread opens a transaction and takes effect
Multi-threading scheme to ensure that a single thread opens a transaction and takes effect
2022-07-30 10:09:00 【silly fish love programming】
When we develop, we often encounter the problem of multi-threaded transactions.I thought it was enough to add the @Transactional annotation. In fact, after you added the annotation, you will find that the transaction is invalid.Reason: The database connection spring is placed in threadLocal. In multi-threaded scenarios, the database connections obtained are different, that is, they belong to different transactions.
Spring supports programmatic transactions and declarative transactions. The most primitive transaction management method provided by Spring is based on TransactionDefinition, PlatformTransactionManager, and TransactionStatus programmatic transactions.
The transaction management of TransactionTemplate is the encapsulation of the original transaction management method using the template method design pattern, so we can also use TransactionTemplate to manage transactions.
Today, let's talk about the solution for a single thread to start a transaction:
1. Propose the thread method directly and add the @Transactional annotation
// Method to enable multithreadingpublic void testTransactional() throws ExecutionException, InterruptedException {int inter = 3;ExecutorService executorService = Executors.newFixedThreadPool(inter);ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) executorService;FutureTask[] integerFuture = new FutureTask[inter];for (int i = 0; i < inter; i++) {int finalI = i + 1;integerFuture[i] = new FutureTask<>(() -> {testTransactionalServiceZi.testTransactionalZi(finalI, "calculation" + finalI);System.out.println("Multiple threads are running---" + finalI);return "Business execution succeeded";});poolExecutor.execute(integerFuture[i]);}for (int i = 0; i < inter; i++) {System.out.println("integerFuture return result = " + i + "==" + integerFuture[i].get());}}// single thread call, add [email protected] void testTransactionalZi(int num, String str) {// modify data ===1===AdCourse adCourse = new AdCourse();adCourse.setId(num);adCourse.setName(str);int i = adCourseMapper.updateById(adCourse);// modify data ===2===adCourse.setId(num + 3);adCourse.setName(str + 0);int result = adCourseMapper.updateById(adCourse);// Manually create an exception (the transaction will take effect)result = 1/0;}2. Use TransactionTemplate to manage transactions
By interpreting the source code, TransactionTemplate encapsulates PlatformTransactionManager.It is more troublesome for us to write PlatformTransactionManager by ourselves to manage transactions, so we use TransactionTemplate to display the code, as follows:
@Servicepublic class TestTransactionalServiceImpl implements TestTransactionalService {@Autowiredprivate TestTransactionalServiceZi testTransactionalServiceZi;// Use Template to control [email protected] TransactionTemplate template;public void testTransactional() throws ExecutionException, InterruptedException {int inter = 3;ExecutorService executorService = Executors.newFixedThreadPool(inter);ThreadPoolExecutor poolExecutor = (ThreadPoolExecutor) executorService;FutureTask[] integerFuture = new FutureTask[inter];for (int i = 0; i < inter; i++) {int finalI = i + 1;integerFuture[i] = new FutureTask<>(() -> {return template.execute(new TransactionCallback() {@Overridepublic String doInTransaction(TransactionStatus transactionStatus) {testTransactionalServiceZi.testTransactionalZi(finalI, "Calculate 666" + finalI);System.out.println("Multiple threads are running---" + finalI);return "Business execution succeeded";}});});poolExecutor.execute(integerFuture[i]);}for (int i = 0; i < inter; i++) {System.out.println("integerFuture return result = " + i + "==" + integerFuture[i].get());}}}// method to callpublic void testTransactionalZi(int num, String str) {// modify data ===1===AdCourse adCourse = new AdCourse();adCourse.setId(num);adCourse.setName(str);int i = adCourseMapper.updateById(adCourse);// modify data ===2===adCourse.setId(num + 3);adCourse.setName(str + 0);int result = adCourseMapper.updateById(adCourse);// Manually create an exception (the transaction will take effect)result = 1/(num-1);} Print result: The first thread did not execute successfully, an exception occurred, and the data did not change.

Summary: The above two methods can guarantee the problem of single thread transaction in multithreading
边栏推荐
猜你喜欢
随机推荐
Day113. Shangyitong: WeChat login QR code, login callback interface
PyQt5快速开发与实战 7.4 事件处理机制入门 and 7.5 窗口数据传递
快解析结合泛微OA
Kotlin value class - value class
线上靶机prompt.ml
Re15:读论文 LEVEN: A Large-Scale Chinese Legal Event Detection Dataset
Always remember: one day you will emerge from the chrysalis
Four ways the Metaverse is changing the way humans work
学习笔记11--局部轨迹直接构造法
Test automation selenium (a)
通过构建一个顺序表——教你计算时间复杂度和空间复杂度(含递归)
Redis Desktop Manager 2022.4.2 发布
Re20:读论文 What About the Precedent: An Information-Theoretic Analysis of Common Law
leetcode 剑指 Offer 10- I. 斐波那契数列
快解析结合象过河erp
你真的懂Redis的5种基本数据结构吗?
九九乘法表
一个近乎完美的 Unity 全平台热更方案
MySQL [operator]
延迟队列MQ









