`
lsk569937453
  • 浏览: 6142 次
文章分类
社区版块
存档分类
最新评论

多线程事务回滚

    博客分类:
  • java
阅读更多
<!--?xml version="1.0" encoding="UTF-8" standalone="no"?-->
周五在java群里看到了一个有意思的问题,周末就顺便实现了一下,需求如下:
考察一个多线程的场景,一个Http Request的controller有10个线程同时并行处理,要求:
1) 主线程必须等待10个线程全部执行成功后主线程返回“Success”
2) 只要其中任意一个线程出错,不仅当前出错的线程要回滚,其他所有线程不管成功失败也要回滚,主线程等待所有线程回滚完毕后输出相应的错误字符“Fail”。 
代码如下:
package com.mfunny.queue;

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingDeque;

/**
 *
 *
 *
 *
 *
 * <p>
 * 修改历史:                                                                                    &lt;br&gt;
 * 修改日期             修改人员        版本                     修改内容
 * --------------------------------------------------------------------
 * 2016年03月26日 上午9:31       1.0   初始化创建
 * </p>
 *
 * @author
 * @version 1.0
 * @since JDK1.7
 */
public class Test {


	private static class Rollback {
		public Rollback(Boolean needRoolBack) {
			this.needRoolBack = needRoolBack;
		}

		private Boolean needRoolBack = false;

		public Boolean getNeedRoolBack() {
			return needRoolBack;
		}

		public void setNeedRoolBack(Boolean needRoolBack) {
			this.needRoolBack = needRoolBack;
		}
	}


	private static class Task implements Runnable {
		/**
		 * 监控10个子任务的执行
		 */
		private CountDownLatch childMonitor;
		/**
		 * 监控主线程
		 */
		private CountDownLatch mainMonitor;

		/**
		 * 存储线程的返回结果
		 */
		private BlockingDeque<Boolean> resultList;
		/**
		 * 回滚类
		 */
		private Rollback rollback;

		public Task(CountDownLatch childCountDown, CountDownLatch mainCountDown, BlockingDeque<Boolean> result, Rollback rollback) {
			this.childMonitor = childCountDown;
			this.mainMonitor = mainCountDown;
			this.resultList = result;
			this.rollback = rollback;
		}

		private void shouldRollBack() {
			System.out.println(Thread.currentThread().getName()+"开始回滚");

		}

		/**
		 * 事务提交
		 */
		private void submit() {
		}

		/**
		 * 执行任务,返回false表示任务执行错误,需要回滚
		 * 本案例中根据线程名字包含Thread-8判断是否回滚
		 * @return
		 */
		private Boolean processTask() {

			if(Thread.currentThread().getName().contains("Thread-8"))
				return false;
			return true;
		}

		@Override public void run() {
			System.out.println(Thread.currentThread().getName()+"子线程开始执行任务");

			Boolean result = processTask();
			//向队列中添加处理结果
			resultList.add(result);
			//等待其他的子线程执行完成,一起执行主线程的判断逻辑
			childMonitor.countDown();
			try {
				//等待主线程的判断逻辑执行完,执行下面的是否回滚逻辑
				mainMonitor.await();
			} catch (Exception e) {
				e.printStackTrace();
			}

			System.out.println(Thread.currentThread().getName()+"子线程执行剩下的任务");
			//需要回滚
			if (rollback.getNeedRoolBack())
				shouldRollBack();
			else
			//不需要回滚->事务提交
				submit();

		}
	}

	public static void main(String[] args) {
		//监控10个子线程的任务执行
		CountDownLatch childMonitor = new CountDownLatch(10);
		//监控主线程,是否需要回滚
		CountDownLatch mainMonitor = new CountDownLatch(1);
		//存储任务的返回结果,返回true表示不需要回滚,反之,则回滚
		BlockingDeque<Boolean> results = new LinkedBlockingDeque<Boolean>(10);

		Rollback rollback = new Rollback(false);

		for (int i = 0; i < 10; i++) {
			//10个任务启动
			Thread thread = new Thread(new Task(childMonitor, mainMonitor, results, rollback));
			thread.start();
		}

		try {

			//监测10个子线程的执行
			childMonitor.await();
			System.out.println("主线程开始执行任务");

			//根据返回结果来确定是否回滚
			for (int i = 0; i < 10; i++) {
				Boolean result = results.take();
				if (!result) {
					rollback.setNeedRoolBack(true);
				}
			}
			//10个子线程开始执行
			mainMonitor.countDown();

			if(rollback.getNeedRoolBack())
				System.out.println("Fail");
			else System.out.println("Success");
		} catch (Exception e) {

		}
	}
}
 思想就是使用两个CountDownWatch实现子线程的二段提交
 
顺便给群打一下广告:
java高级群(329019348)
java水群(51317874)
1
4
分享到:
评论

相关推荐

    SpringBoot事务使用及回滚实现代码详解

    事务是指一组操作的集合,作为一个单元执行,如果其中任何一个操作失败,则整个事务回滚,保证数据的一致性。 在SpringBoot中,事务的使用需要在启动类上添加@EnableTransactionManagement注解,以开启事务支持。...

    子线程任务发生异常,主线程事务如何回滚

    下面将从多线程编程的基础知识、线程池的使用、异常捕获三个方面进行阐述。 一、多线程编程基础知识 在 Java 中,存在两种线程模型:主线程和子线程。主线程是程序的入口点,而子线程是由主线程创建的辅助线程。...

    spring boot注解事务+多线程

    在Spring Boot应用中,事务管理和多线程是两个非常关键的特性,特别是在处理复杂的业务逻辑时。本示例将深入探讨如何使用注解来实现事务控制以及如何在Spring Boot中运用多线程。 首先,让我们关注"注解事务"。在...

    异步线程AsyncTask

    Android的AsyncTask比Handler更轻量级一些 适用于简单的异步处理 首先明确Android之所以有Handler和AsyncTask 都是为了不阻塞主线程(UI线程) 且UI的更新只能在主线程中完成 因此异步...Android为了降低这个开 [更多]

    springboot中多线程事务的实现

    springboot中多线程事务的实现,整个springboot和多线程,任何一个线程异常,则每个线程的事务都回滚,保证事务的一致性

    [] - 2023-01-10 支付宝:多线程事务怎么回滚?说用 @Transactional 可以回去等通知了!.pdf

    互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术,人工智能互联网资讯,技术简介,IT、AI技术...

    QT中sqlite多线程操作4个注意问题

    3. **事务处理**: 在多线程环境中,确保每个线程的写入操作在自己的事务中进行,这样可以提高并发性并减少数据一致性风险。使用`beginTransaction()`、`commit()`和`rollback()`来管理事务。如果一个线程的事务未...

    Java多线程详解及示例

    - 检测和恢复死锁:定期检查系统状态,检测到死锁后,可以终止某个线程或者回滚事务来打破死锁状态。 4. 线程池 Java提供了ExecutorService和ThreadPoolExecutor类来管理线程,创建线程池可以有效控制并发线程的...

    MulThreadSQLiteTest多线程操作数据库

    在多线程环境下,每个线程应在其事务内完成所有操作,一旦出现错误,可以通过回滚事务撤销所有更改。 4. **锁机制**:在某些情况下,可能需要手动使用锁来控制对数据库的访问,例如读写锁。读锁允许多个线程同时...

    易语言多线程同时查询同一数据库

    综上所述,易语言多线程同时查询同一数据库的技术实现涉及到多线程编程原理、数据库访问控制、事务管理、查询优化、错误处理和线程通信等多个知识点。通过熟练掌握这些技术,开发者可以构建出高效且稳定的数据库查询...

    java简单分布式架构,多个数据源,线程池多线程访问

    综上所述,这个项目涉及到的知识点包括:分布式系统设计、Java多线程与线程池、Spring框架的多数据源支持、MyBatis的使用以及Spring的事务管理。通过这些技术的组合,可以构建出一个高效、可扩展的分布式应用,以...

    java多线程模拟处理银行的实时转账交易

    总的来说,这个项目涵盖了Java多线程编程中的诸多重要知识点,包括线程创建与管理、并发控制、异常处理、事务一致性以及测试。通过实际操作,开发者可以深入理解并掌握这些关键概念和技术,提升自己的编程能力。

    一个多线程访问数据库的代码

    2. 事务管理:为了确保数据的一致性,可能需要使用事务来包围一组数据库操作,确保它们要么全部成功,要么全部回滚。 3. 错误处理:多线程环境中的错误处理更加复杂,需要考虑线程间的通信和异常处理。 4. 性能优化...

    windows多线程的同步和互斥

    4. **死锁检测和恢复**:系统能够检测到死锁,并采取措施如回滚事务、取消部分线程等。 总结,Windows多线程的同步和互斥机制是解决并发编程中数据安全和效率的关键。通过合理利用临界区、事件、互斥量、信号量等...

    多线程介绍及如何避免死锁.zip

    4. 死锁检测与恢复:通过系统监控,检测到死锁后,可以强制终止某个线程或者回滚事务来打破循环。 5. 预防策略:比如银行家算法,预先分配资源,确保不会出现无法满足的资源请求。 在实际应用中,我们还需要关注...

    多线程使用FMDB操作sqlite数据库

    本文将深入探讨如何在多线程环境中使用FMDB进行SQLite数据库的操作。 ### 多线程环境中的SQLite SQLite本身并不支持完全的多线程操作,它允许同时有多个读取操作,但只有一个写入操作。这意味着在多线程环境下,...

    python 多线程操作MySQL读写脚本

    总的来说,"python 多线程操作MySQL读写脚本"涉及了Python多线程编程、MySQL数据库操作、事务管理、并发控制、连接保持和文件操作等多个方面。在实现这样的脚本时,需要充分理解这些概念,并注意处理好并发带来的...

    插入数据多线程例子

    6. **错误处理和回滚**:在多线程环境中,必须考虑到线程可能会抛出异常,因此需要有适当的错误处理机制,例如使用try-catch-finally块来捕获和处理异常,并在必要时回滚事务。 7. **线程同步**:如果多个线程需要...

    易语言源码多线程数据库查询对比源码.zip

    2. **事务管理**:如果数据库操作需要事务支持,确保每个线程内的事务能够正确提交或回滚,保证数据一致性。 3. **线程安全**:数据库连接通常不建议在多线程间共享,因为不同线程可能会并发地修改连接状态,应为每...

Global site tag (gtag.js) - Google Analytics