范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

支付宝一面多线程事务怎么回滚?

  背景介绍
  1.最近有一个大数据量插入的操作入库的业务场景,需要先做一些其他修改操作,然后在执行插入操作,由于插入数据可能会很多,用到多线程去拆分数据并行处理来提高响应时间,如果有一个线程执行失败,则全部回滚。
  2.在spring中可以使用@Transactional注解去控制事务,使出现异常时会进行回滚,在多线程中,这个注解则不会生效,如果主线程需要先执行一些修改数据库的操作,当子线程在进行处理出现异常时,主线程修改的数据则不会回滚,导致数据错误。
  3.下面用一个简单示例演示多线程事务。 公用的类和方法/**  * 平均拆分list方法.  * @param source  * @param n  * @param   * @return  */ public static  List> averageAssign(List source,int n){     List> result=new ArrayList>();     int remaider=source.size()%n;      int number=source.size()/n;      int offset=0;//偏移量     for(int i=0;i value=null;         if(remaider>0){             value=source.subList(i*number+offset, (i+1)*number+offset+1);             remaider--;             offset++;         }else{             value=source.subList(i*number+offset, (i+1)*number+offset);         }         result.add(value);     }     return result; } /**  线程池配置  * @version V1.0  */ public class ExecutorConfig {     private static int maxPoolSize = Runtime.getRuntime().availableProcessors();     private volatile static ExecutorService executorService;     public static ExecutorService getThreadPool() {         if (executorService == null){             synchronized (ExecutorConfig.class){                 if (executorService == null){                     executorService =  newThreadPool();                 }             }         }         return executorService;     }      private static  ExecutorService newThreadPool(){         int queueSize = 500;         int corePool = Math.min(5, maxPoolSize);         return new ThreadPoolExecutor(corePool, maxPoolSize, 10000L, TimeUnit.MILLISECONDS,             new LinkedBlockingQueue<>(queueSize),new ThreadPoolExecutor.AbortPolicy());     }     private ExecutorConfig(){} } /** 获取sqlSession  * @author 86182  * @version V1.0  */ @Component public class SqlContext {     @Resource     private SqlSessionTemplate sqlSessionTemplate;      public SqlSession getSqlSession(){         SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory();         return sqlSessionFactory.openSession();     } } 示例事务不成功操作/**  * 测试多线程事务.  * @param employeeDOList  */ @Override @Transactional public void saveThread(List employeeDOList) {     try {         //先做删除操作,如果子线程出现异常,此操作不会回滚         this.getBaseMapper().delete(null);         //获取线程池         ExecutorService service = ExecutorConfig.getThreadPool();         //拆分数据,拆分5份         List> lists=averageAssign(employeeDOList, 5);         //执行的线程         Thread []threadArray = new Thread[lists.size()];         //监控子线程执行完毕,再执行主线程,要不然会导致主线程关闭,子线程也会随着关闭         CountDownLatch countDownLatch = new CountDownLatch(lists.size());         AtomicBoolean atomicBoolean = new AtomicBoolean(true);         for (int i =0;i list  = lists.get(i);             threadArray[i] =  new Thread(() -> {                 try {                  //最后一个线程抛出异常                     if (!atomicBoolean.get()){                         throw new ServiceException("001","出现异常");                     }                     //批量添加,mybatisPlus中自带的batch方法                     this.saveBatch(list);                 }finally {                     countDownLatch.countDown();                 }              });         }         for (int i = 0; i  employeeDOList = new ArrayList<>(size);         for (int i = 0; i employeeDOList) throws SQLException {     // 获取数据库连接,获取会话(内部自有事务)     SqlSession sqlSession = sqlContext.getSqlSession();     Connection connection = sqlSession.getConnection();     try {         // 设置手动提交         connection.setAutoCommit(false);         //获取mapper         EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);         //先做删除操作         employeeMapper.delete(null);         //获取执行器         ExecutorService service = ExecutorConfig.getThreadPool();         List> callableList  = new ArrayList<>();         //拆分list         List> lists=averageAssign(employeeDOList, 5);         AtomicBoolean atomicBoolean = new AtomicBoolean(true);         for (int i =0;i list  = lists.get(i);             //使用返回结果的callable去执行,             Callable callable = () -> {                 //让最后一个线程抛出异常                 if (!atomicBoolean.get()){                     throw new ServiceException("001","出现异常");                 }               return employeeMapper.saveBatch(list);             };             callableList.add(callable);         }         //执行子线程        List> futures = service.invokeAll(callableList);         for (Future future:futures) {         //如果有一个执行不成功,则全部回滚             if (future.get()<=0){                 connection.rollback();                  return;             }         }         connection.commit();         System.out.println("添加完毕");     }catch (Exception e){         connection.rollback();         log.info("error",e);         throw new ServiceException("002","出现异常");     }finally {          connection.close();      } } // sql   INSERT INTO  employee (employee_id,age,employee_name,birth_date,gender,id_number,creat_time,update_time,status)  values            (      #{item.employeeId},      #{item.age},      #{item.employeeName},      #{item.birthDate},      #{item.gender},      #{item.idNumber},      #{item.creatTime},      #{item.updateTime},      #{item.status}          )        
  数据库中一条数据:
  测试结果,抛出异常:
  删除操作的数据回滚了,数据库中的数据依旧存在,说明事务成功了。
  成功操作示例: @Resource SqlContext sqlContext; /**  * 测试多线程事务.  * @param employeeDOList  */ @Override public void saveThread(List employeeDOList) throws SQLException {     // 获取数据库连接,获取会话(内部自有事务)     SqlSession sqlSession = sqlContext.getSqlSession();     Connection connection = sqlSession.getConnection();     try {         // 设置手动提交         connection.setAutoCommit(false);         EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);         //先做删除操作         employeeMapper.delete(null);         ExecutorService service = ExecutorConfig.getThreadPool();         List> callableList  = new ArrayList<>();         List> lists=averageAssign(employeeDOList, 5);         for (int i =0;i list  = lists.get(i);             Callable callable = () -> employeeMapper.saveBatch(list);             callableList.add(callable);         }         //执行子线程        List> futures = service.invokeAll(callableList);         for (Future future:futures) {             if (future.get()<=0){                 connection.rollback();                  return;             }         }         connection.commit();         System.out.println("添加完毕");     }catch (Exception e){         connection.rollback();         log.info("error",e);         throw new ServiceException("002","出现异常");        // throw new ServiceException(ExceptionCodeEnum.EMPLOYEE_SAVE_OR_UPDATE_ERROR);     } }
  测试结果:
  数据库中数据:
  删除的删除了,添加的添加成功了,测试成功。
  来源:blog.csdn.net/weixin_43225491/article/details/117705686

RedmiK50宇宙来袭RedmiK40系列是2021的一匹黑马。它在618年赢得了销售冠军,半年多来价格几乎没有波动。可以看出这个模型有多香。(主要是12256g版本)虽然K40的价格相对较低,还有使用骑行井陉九莲洞挂云山骑行井陉九莲洞挂云山爬山农历初三,天气晴好,零下6度,微风23级,适合骑行和爬山。计划骑行到九莲洞,看看溶洞。然后再去挂云山,全程100公里,力度适中。挂云山风景骑行组7点出发,十最便宜的34英寸120Hz4K电竞带鱼屏亲测靠谱放心买21934英寸高刷新率带鱼屏,这四个关键字放在一起,不少人的第一反应是这得很贵吧?放在几年以前,这几个参数放一起显然便宜不到哪去,而现在,随着面板成本降低,带鱼屏的价格也逐渐降了下共享冬奥盛会照金滑雪场好火热随着北京冬奥会的正式开启,冰雪运动热情彻底被点燃。2月5日,照金滑雪场在严格落实疫情防控各项措施的前提下,迎来了今冬以来最大的客流量,单日入场游客数量突破5000人大关。来自西安的献礼冬奥八位小歌手唱响冰雪相约2022北京冬奥会即将拉开帷幕。近日,由范坤作曲,王砚玺丁海涛作词,邵爱然崔雅瑄贾子峻刘奕焓张艺潇郭恩泽张爱卿秦梓迅八位小歌手演唱的歌曲冰雪相约发布MV,为冬奥献礼。2022冬奥会冬奥会复兴号5G智能列车震惊外国媒体,感叹中国科技至少领先10年2022年北京冬奥会,外国记者来到中国,第一时间就被中国的一系列科技所震撼。公寓入住移动售货社区配送点菜送餐客房服务导览翻译安防巡检颁奖器械运送等九大场景,无不彰显中国科技崛起迅速京西小三峡丨不出京感受低配版雅鲁藏布江大拐弯丨附详细攻略新年登高,这一次选择的是位于北京市门头沟珠窝村的京西小三峡。导航至珠窝村,上山的路不需要进村,但是需要在村口门卫处扫健康宝。上山路就是三岔路口的中间岔路,一路向北,沿途路左侧有一个美国媒体爆料,法拉第可能卖不出一辆车,贾跃亭被认定是骗子?2017年,乐视系崩盘。贾跃亭于当年7月份远赴美国造车,至今未归!说句实话,这几年但凡是贾跃亭的新闻,基本上都是负面的。为何呢?因为在大部分人眼中,贾跃亭俨然成为了一个骗子。都说阿一爬到底的宝宝更聪明?错过爬行期难补救,要学会引导文宋妈说育儿(原创文章,欢迎转载分享)老话说三翻六坐,七牙八爬,从字面意思不难看出,宝宝大约八九个月大时,就会爬了。当然,并非所有宝宝都按照固定套路出牌,一些宝宝一岁多还不会爬,甚养二胎比养一胎要多花钱?宝妈晒年度养娃账单,结果和你想的不同普遍想法是,养两个孩子的花销要比养一个多很多。一提到二胎,很多父母想到的第一个制约条件是穷。觉得以自己现在的经济条件,很难供给两个孩子的花销。毕竟孩子的吃穿用度都要花钱,不管上不上怀孕期间如何保胎?做好这几点,保证胎儿健康平安十月怀胎,一朝分娩,怀孕期间虽然辛苦,但很快乐,能跟胎儿共同享受心跳和血液。对孕妇来说,胎儿健康是最为重要的,整个怀孕期应做到以下几点来保证胎儿健康平安。怀孕期间该如何保胎?1多注
滴滴563天后回归,网约车江湖已风起云涌经历了563天的冰封期,滴滴出行终于回来了。1月16日,滴滴出行对外宣布,经报网络安全审查办公室同意,即日起恢复滴滴出行的新用户注册。滴滴出行同时提到,一年多来,我公司认真配合国家三天后,南康三大区域实行交通管制!转发提醒为确保2023年大年三十,正月初一十五节日期间南山森林公园家居特色小镇旅游区及区文化广场燃放烟花活动期间道路安全有序畅通,区公安交管大队将在大年三十正月初一及十五对三个景区周边道路李航俞栋梅宏当选ACMFellow!今年57人新名单华人占14位萧箫发自凹非寺量子位公众号QbitAI就在刚刚,2022年ACMFellow最新名单出炉!今年一共新增57位Fellow,其中华人学者就有14位。包括清华大学教授朱文武北京大学教授行吟诗刊丨北琪张家界山水之境金鞭溪烟雨。张家界山水之境(组诗)脚踏山水所有的铺垫只为最后这一刻一步登天,多么诱人的景点我承认,登山的过程不仅仅为了看风景,更想凌驾于高山之上站在山巅,我想要的不过是,在心里种荷专访张家界常务副总裁董秘金鑫春节旅游爆火,景区导游紧缺行业的春天来了吗?每经记者于垚峰程雅每经编辑魏官红2023年的春节假期,国内各大景区迎来了客流高峰,人从众成为春节出游的真实写照,热闹的气氛让不少旅游行业从业者感慨春天来了。但是,热闹的情形可持续吗从黄山张家界说起预判失误,不应再成为景区的挡箭牌这个春节,景区大热,人山人海熙熙攘攘。但热闹的气息之外,有些景区,却因为未能及时预判游客滞留,让春节之旅成了再也不敢来的烦恼之旅济南文华女士一家三口,就在刚刚过去的大年初三,亲身体张家界天门山景区索道轿厢悬停1分钟?景区电源切换停车1月27日,有网友在短视频平台上发文称1月26日中午,湖南省张家界天门山景区内索道停电导致轿厢悬停的情况,悬停时长达1分多钟。该视频随即引起热议,甚至有网友评论说曾经悬挂了半个小时冬游张家界有一种旅行叫一起去张家界吃冬天的第一根雪糕红网时刻记者李森林报道看美景吃雪糕,今年春节假期,张家界国家森林公园文创雪糕引游客纷纷打卡,冬天的第一根雪糕为游客带来不一样的旅行仪式感,文创雪糕的独特文化IP元素与自然美景深度融霍华德马克斯的正收益,背后有三件最重要的事2022年唯一正收益的投资大师教你如何应对风险文财经记者张云编辑王立峰说起橡树资本联席创始人及联席董事长霍华德马克斯,不少投资者的印象停留在他所写的两本书投资最重要的事和周期。但马坏消息!泰山队心仪的新援被意外截胡,未来将代表成都蓉城出战日前,大连队离队飞翼孙国文的新东家敲定,他即将签约上赛季中超黑马成都蓉城。孙国文跟大连队合约到期后,他并没有选择续约。相反,孙国文希望能离队转会,开启职业生涯新篇章。由于孙国文在大阿里贾扬清新一轮AI爆发的推动机制是工程化和开源MEET2023羿阁整理自MEET2023量子位公众号QbitAI随着StableDiffusionChatGPT的爆火,AI在今年迎来了大爆发。这不禁让人想问,这些创新背后的推动机制究竟是什么?