Springboot多线程事务回滚(改良版)

前段时间发过此类demo,后经大神改版,学到了一点,遂记录一下

 1     /**
 2      * 利用线程池起两个任务
 3      */
 4     public String thredSubmit(String uuidStr, List<VariationMapIn> mapIns, List<ApproveHis> hisList, String[] ids,
 5             Long guToJuPartyId) {
 6         SubmitToPer submitToPerTask = new SubmitToPer(uuidStr, hisList, mapIns,
 7                 JtCommonUtil.getUserView().getPartyId());
 8 
 9         XianSubmit xianianSubmitTask = new XianSubmit(JtCommonUtil.getUserView().getOrganization().getGroupCode(),
10                 mapIns, JtCommonUtil.getUserView().getPartyId());
11 
12         String result = SynTaskUtils.doWork(Arrays.asList(submitToPerTask, xianianSubmitTask), transactionManager);
13         return result;
14     }
 1 /**
 2  * 第一个任务
 3  */
 4 public class SubmitToPer extends BaseCallBack {
 5 
 6     private String uuidStr;
 7     private List<ApproveHis> hisList;
 8     private List<VariationMapIn> mapIns;
 9     private Long partyId;
10 
11     public SubmitToPer(String uuidStr, List<ApproveHis> hisList, List<VariationMapIn> mapIns, Long partyId) {
12         super();
13         this.uuidStr = uuidStr;
14         this.hisList = hisList;
15         this.mapIns = mapIns;
16         this.partyId = partyId;
17     }
18 
19     @Override
20     protected void doWork() {
21         // 业务处理开始
22         MapInDealService mapInDealService = (MapInDealService) ApplicationUtil.getBean("mapInDealService");
23         mapInDealService.submitToPer(uuidStr, mapIns, hisList, partyId);
24     }
25 
26 }
 1 /**
 2  * 第二个任务
 3  */
 4 public class XianSubmit extends BaseCallBack {
 5 
 6     private String groupCode;
 7     private List<VariationMapIn> mapIns;
 8     private Long partyId;
 9 
10     public XianSubmit(String groupCode, List<VariationMapIn> mapIns, Long partyId) {
11         super();
12         this.groupCode = groupCode;
13         this.mapIns = mapIns;
14         this.partyId = partyId;
15     }
16 
17     @Override
18     protected void doWork() {
19         SpanCheckService spanCheckService = (SpanCheckService) ApplicationUtil.getBean("spanCheckService");
20         String str = spanCheckService.xianCheckIn(mapIns, partyId, groupCode);
21         if (!Constant.SUCCESS_STR.equals(str))
22             throw new RuntimeException(str);
23     }
24 
25 }
  1 /**
  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 }
 1 /**
 2  * 异步线程执行器 携带回滚
 3  * 
 4  * @author Administrator
 5  *
 6  */
 7 public class SynTaskUtils {
 8 
 9     /**
10      * 日志
11      */
12     private static Logger logger = LoggerFactory.getLogger(SynTaskUtils.class);
13 
14     public static String doWork(List<? extends BaseCallBack> tasks, PlatformTransactionManager transactionManager) {
15         if (tasks == null || tasks.size() <= 0) {
16             return Constant.SUCCESS_STR;
17         }
18         logger.info("开始执行一组线程..........................................................");
19         CountDownLatch rollBackLatch = new CountDownLatch(1);
20         CountDownLatch mainThreadLatch = new CountDownLatch(tasks.size());
21         AtomicBoolean rollbackFlag = new AtomicBoolean(false);
22         List<Future<String>> list = new ArrayList<Future<String>>();
23         for (BaseCallBack task : tasks) {
24             task.setMainThreadLatch(mainThreadLatch);
25             task.setRollbackFlag(rollbackFlag);
26             task.setRollBackLatch(rollBackLatch);
27             task.setTransactionManager(transactionManager);
28             logger.info("添加任务:{}", task.getClass().getName());
29             Future<String> future = TestExecutorUtil.getInstance().getExecutor().submit(task);
30             list.add(future);
31         }
32         // 主线程业务执行完毕 如果其他线程也执行完毕 且没有报异常 正在阻塞状态中 唤醒其他线程 提交所有的事务
33         // 如果其他线程或者主线程报错 则不会进入if 会触发回滚
34         try {
35             logger.info("主线程开始等待。");
36             mainThreadLatch.await();
37             logger.info("主线程等待结束。");
38             if (!rollbackFlag.get()) {
39                 logger.info("不需要回滚。");
40                 rollBackLatch.countDown();
41                 return Constant.SUCCESS_STR;
42             } else {
43                 logger.info("需要回滚。");
44                 for (Future<String> f : list) {
45                     String result = f.get();
46                     if (!Constant.SAVE_SUCCESS.equals(result)) {
47                         logger.info("返回值:{}", result);
48                         return result;
49                     }
50                 }
51                 return Constant.SUCCESS_STR;
52             }
53         } catch (Exception e) {
54             return "操作出现异常。";
55         }finally {
56             logger.info("结束执行一组线程..........................................................");
57         }
58     }
59 
60 }
 1 /**
 2  * 公用线程池
 3  * 
 4  * @author Administrator
 5  *
 6  */
 7 public class TestExecutorUtil {
 8 
 9     /**
10      * 线程池
11      */
12     private ExecutorService executor = Executors.newFixedThreadPool(10);
13 
14     /**
15      * 单利
16      * 
17      * @author Administrator
18      *
19      */
20     private static class Instance {
21         private static final TestExecutorUtil instance = new TestExecutorUtil();
22     }
23 
24     private TestExecutorUtil() {
25     }
26 
27     public static TestExecutorUtil getInstance() {
28         return Instance.instance;
29     }
30 
31     public TestExecutorService getExecutor() {
32         return executor;
33     }
34 
35 }

 

posted @ 2020-11-13 14:35  天冷吃冰棍儿  阅读(6092)  评论(0编辑  收藏  举报