女人自慰AV免费观看内涵网,日韩国产剧情在线观看网址,神马电影网特片网,最新一级电影欧美,在线观看亚洲欧美日韩,黄色视频在线播放免费观看,ABO涨奶期羡澄,第一导航fulione,美女主播操b

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

支付寶:多線程事務(wù)怎么回滾?

jf_ro2CN3Fa ? 來(lái)源:CSDN ? 2023-01-09 11:42 ? 次閱讀


背景介紹

1,最近有一個(gè)大數(shù)據(jù)量插入的操作入庫(kù)的業(yè)務(wù)場(chǎng)景,需要先做一些其他修改操作,然后在執(zhí)行插入操作,由于插入數(shù)據(jù)可能會(huì)很多,用到多線程去拆分?jǐn)?shù)據(jù)并行處理來(lái)提高響應(yīng)時(shí)間,如果有一個(gè)線程執(zhí)行失敗,則全部回滾。

2,在spring中可以使用@Transactional注解去控制事務(wù),使出現(xiàn)異常時(shí)會(huì)進(jìn)行回滾,在多線程中,這個(gè)注解則不會(huì)生效,如果主線程需要先執(zhí)行一些修改數(shù)據(jù)庫(kù)的操作,當(dāng)子線程在進(jìn)行處理出現(xiàn)異常時(shí),主線程修改的數(shù)據(jù)則不會(huì)回滾,導(dǎo)致數(shù)據(jù)錯(cuò)誤。

3,下面用一個(gè)簡(jiǎn)單示例演示多線程事務(wù)。

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

  • 項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

公用的類(lèi)和方法

/**
*平均拆分list方法.
*@paramsource
*@paramn
*@param
*@return
*/
publicstaticList>averageAssign(Listsource,intn){
List>result=newArrayList>();
intremaider=source.size()%n;
intnumber=source.size()/n;
intoffset=0;//偏移量
for(inti=0;ivalue=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);
}
returnresult;
}
/**線程池配置
*@versionV1.0
*/
publicclassExecutorConfig{
privatestaticintmaxPoolSize=Runtime.getRuntime().availableProcessors();
privatevolatilestaticExecutorServiceexecutorService;
publicstaticExecutorServicegetThreadPool(){
if(executorService==null){
synchronized(ExecutorConfig.class){
if(executorService==null){
executorService=newThreadPool();
}
}
}
returnexecutorService;
}

privatestaticExecutorServicenewThreadPool(){
intqueueSize=500;
intcorePool=Math.min(5,maxPoolSize);
returnnewThreadPoolExecutor(corePool,maxPoolSize,10000L,TimeUnit.MILLISECONDS,
newLinkedBlockingQueue<>(queueSize),newThreadPoolExecutor.AbortPolicy());
}
privateExecutorConfig(){}
}
/**獲取sqlSession
*@author86182
*@versionV1.0
*/
@Component
publicclassSqlContext{
@Resource
privateSqlSessionTemplatesqlSessionTemplate;

publicSqlSessiongetSqlSession(){
SqlSessionFactorysqlSessionFactory=sqlSessionTemplate.getSqlSessionFactory();
returnsqlSessionFactory.openSession();
}
}

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶(hù)小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶(hù)、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

  • 項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

示例事務(wù)不成功操作

/**
*測(cè)試多線程事務(wù).
*@paramemployeeDOList
*/
@Override
@Transactional
publicvoidsaveThread(ListemployeeDOList){
try{
//先做刪除操作,如果子線程出現(xiàn)異常,此操作不會(huì)回滾
this.getBaseMapper().delete(null);
//獲取線程池
ExecutorServiceservice=ExecutorConfig.getThreadPool();
//拆分?jǐn)?shù)據(jù),拆分5份
List>lists=averageAssign(employeeDOList,5);
//執(zhí)行的線程
Thread[]threadArray=newThread[lists.size()];
//監(jiān)控子線程執(zhí)行完畢,再執(zhí)行主線程,要不然會(huì)導(dǎo)致主線程關(guān)閉,子線程也會(huì)隨著關(guān)閉
CountDownLatchcountDownLatch=newCountDownLatch(lists.size());
AtomicBooleanatomicBoolean=newAtomicBoolean(true);
for(inti=0;iif(i==lists.size()-1){
atomicBoolean.set(false);
}
Listlist=lists.get(i);
threadArray[i]=newThread(()->{
try{
//最后一個(gè)線程拋出異常
if(!atomicBoolean.get()){
thrownewServiceException("001","出現(xiàn)異常");
}
//批量添加,mybatisPlus中自帶的batch方法
this.saveBatch(list);
}finally{
countDownLatch.countDown();
}

});
}
for(inti=0;i//當(dāng)子線程執(zhí)行完畢時(shí),主線程再往下執(zhí)行
countDownLatch.await();
System.out.println("添加完畢");
}catch(Exceptione){
log.info("error",e);
thrownewServiceException("002","出現(xiàn)異常");
}finally{
connection.close();
}
}

數(shù)據(jù)庫(kù)中存在一條數(shù)據(jù):

07f6f516-8fc2-11ed-bfe3-dac502259ad0.png
//測(cè)試用例
@RunWith(SpringRunner.class)
@SpringBootTest(classes={ThreadTest01.class,MainApplication.class})
publicclassThreadTest01{

@Resource
privateEmployeeBOemployeeBO;

/**
*測(cè)試多線程事務(wù).
*@throwsInterruptedException
*/
@Test
publicvoidMoreThreadTest2()throwsInterruptedException{
intsize=10;
ListemployeeDOList=newArrayList<>(size);
for(inti=0;inewEmployeeDO();
employeeDO.setEmployeeName("lol"+i);
employeeDO.setAge(18);
employeeDO.setGender(1);
employeeDO.setIdNumber(i+"XX");
employeeDO.setCreatTime(Calendar.getInstance().getTime());
employeeDOList.add(employeeDO);
}
try{
employeeBO.saveThread(employeeDOList);
System.out.println("添加成功");
}catch(Exceptione){
e.printStackTrace();
}
}
}

測(cè)試結(jié)果:

08028656-8fc2-11ed-bfe3-dac502259ad0.png08120248-8fc2-11ed-bfe3-dac502259ad0.png

可以發(fā)現(xiàn)子線程組執(zhí)行時(shí),有一個(gè)線程執(zhí)行失敗,其他線程也會(huì)拋出異常,但是主線程中執(zhí)行的刪除操作,沒(méi)有回滾,@Transactional注解沒(méi)有生效。

使用sqlSession控制手動(dòng)提交事務(wù)

@Resource
SqlContextsqlContext;
/**
*測(cè)試多線程事務(wù).
*@paramemployeeDOList
*/
@Override
publicvoidsaveThread(ListemployeeDOList)throwsSQLException{
//獲取數(shù)據(jù)庫(kù)連接,獲取會(huì)話(內(nèi)部自有事務(wù))
SqlSessionsqlSession=sqlContext.getSqlSession();
Connectionconnection=sqlSession.getConnection();
try{
//設(shè)置手動(dòng)提交
connection.setAutoCommit(false);
//獲取mapper
EmployeeMapperemployeeMapper=sqlSession.getMapper(EmployeeMapper.class);
//先做刪除操作
employeeMapper.delete(null);
//獲取執(zhí)行器
ExecutorServiceservice=ExecutorConfig.getThreadPool();
List>callableList=newArrayList<>();
//拆分list
List>lists=averageAssign(employeeDOList,5);
AtomicBooleanatomicBoolean=newAtomicBoolean(true);
for(inti=0;iif(i==lists.size()-1){
atomicBoolean.set(false);
}
Listlist=lists.get(i);
//使用返回結(jié)果的callable去執(zhí)行,
Callablecallable=()->{
//讓最后一個(gè)線程拋出異常
if(!atomicBoolean.get()){
thrownewServiceException("001","出現(xiàn)異常");
}
returnemployeeMapper.saveBatch(list);
};
callableList.add(callable);
}
//執(zhí)行子線程
List>futures=service.invokeAll(callableList);
for(Futurefuture:futures){
//如果有一個(gè)執(zhí)行不成功,則全部回滾
if(future.get()<=0){
connection.rollback();
return;
}
}
connection.commit();
System.out.println("添加完畢");
}catch(Exceptione){
connection.rollback();
log.info("error",e);
thrownewServiceException("002","出現(xiàn)異常");
}finally{
connection.close();
}
}
//sql
"saveBatch"parameterType="List">
INSERTINTO
employee(employee_id,age,employee_name,birth_date,gender,id_number,creat_time,update_time,status)
values
="list"item="item"index="index"separator=",">
(
#{item.employeeId},
#{item.age},
#{item.employeeName},
#{item.birthDate},
#{item.gender},
#{item.idNumber},
#{item.creatTime},
#{item.updateTime},
#{item.status}
)


數(shù)據(jù)庫(kù)中一條數(shù)據(jù):

081f036c-8fc2-11ed-bfe3-dac502259ad0.png

測(cè)試結(jié)果:拋出異常,

0836bc00-8fc2-11ed-bfe3-dac502259ad0.png

刪除操作的數(shù)據(jù)回滾了,數(shù)據(jù)庫(kù)中的數(shù)據(jù)依舊存在,說(shuō)明事務(wù)成功了。

0847e7d2-8fc2-11ed-bfe3-dac502259ad0.png

成功操作示例:

@Resource
SqlContextsqlContext;
/**
*測(cè)試多線程事務(wù).
*@paramemployeeDOList
*/
@Override
publicvoidsaveThread(ListemployeeDOList)throwsSQLException{
//獲取數(shù)據(jù)庫(kù)連接,獲取會(huì)話(內(nèi)部自有事務(wù))
SqlSessionsqlSession=sqlContext.getSqlSession();
Connectionconnection=sqlSession.getConnection();
try{
//設(shè)置手動(dòng)提交
connection.setAutoCommit(false);
EmployeeMapperemployeeMapper=sqlSession.getMapper(EmployeeMapper.class);
//先做刪除操作
employeeMapper.delete(null);
ExecutorServiceservice=ExecutorConfig.getThreadPool();
List>callableList=newArrayList<>();
List>lists=averageAssign(employeeDOList,5);
for(inti=0;ilist=lists.get(i);
Callablecallable=()->employeeMapper.saveBatch(list);
callableList.add(callable);
}
//執(zhí)行子線程
List>futures=service.invokeAll(callableList);
for(Futurefuture:futures){
if(future.get()<=0){
connection.rollback();
return;
}
}
connection.commit();
System.out.println("添加完畢");
}catch(Exceptione){
connection.rollback();
log.info("error",e);
thrownewServiceException("002","出現(xiàn)異常");
//thrownewServiceException(ExceptionCodeEnum.EMPLOYEE_SAVE_OR_UPDATE_ERROR);
}
}

測(cè)試結(jié)果:

08585db0-8fc2-11ed-bfe3-dac502259ad0.png

數(shù)據(jù)庫(kù)中數(shù)據(jù):

刪除的刪除了,添加的添加成功了,測(cè)試成功。

0869dc84-8fc2-11ed-bfe3-dac502259ad0.png

審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 多線程
    +關(guān)注

    關(guān)注

    0

    文章

    279

    瀏覽量

    20308
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14879

原文標(biāo)題:支付寶:多線程事務(wù)怎么回滾?說(shuō)用 @Transactional 可以回去等通知了!

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    復(fù)旦微電子與支付寶推出“碰一下”射頻芯片

    近日,由支付寶主辦的「碰一下·奇妙小鎮(zhèn)」生態(tài)大會(huì)在杭州·運(yùn)河文化發(fā)布中心隆重舉辦。大會(huì)場(chǎng)景覆蓋餐飲、商圈MALL、出行、政務(wù)、醫(yī)療、物流等多個(gè)領(lǐng)域,以服務(wù)商、供應(yīng)鏈伙伴和終端廠商為代表的生態(tài)伙伴共同參與,超300家頭部合作伙伴創(chuàng)始人/CEO參加大會(huì)。
    的頭像 發(fā)表于 04-28 09:46 ?272次閱讀

    請(qǐng)問(wèn)rt-thread studio如何進(jìn)行多線程編譯?

    ,使用的是5800h+32g內(nèi)存+sn550 ssd,開(kāi)啟16線程編譯時(shí)cpu的占用率也只能到30%,編譯完整個(gè)工程需要3分鐘 感覺(jué)多線程編譯設(shè)置沒(méi)有生效,有辦法提高編譯速度嗎
    發(fā)表于 02-19 08:30

    支付寶發(fā)布新一代AI視覺(jué)搜索“探一下”

    支付寶近日正式推出了基于自研多模態(tài)大模型技術(shù)的新一代AI視覺(jué)搜索產(chǎn)品——“探一下”。這一創(chuàng)新產(chǎn)品的問(wèn)世,標(biāo)志著支付寶在AI技術(shù)應(yīng)用領(lǐng)域邁出了重要一步。 “探一下”通過(guò)集成先進(jìn)的AI技術(shù),使用戶(hù)能夠
    的頭像 發(fā)表于 12-31 10:49 ?490次閱讀

    socket 多線程編程實(shí)現(xiàn)方法

    在現(xiàn)代網(wǎng)絡(luò)編程中,多線程技術(shù)被廣泛應(yīng)用于提高服務(wù)器的并發(fā)處理能力。Socket編程是網(wǎng)絡(luò)通信的基礎(chǔ),而將多線程技術(shù)應(yīng)用于Socket編程,可以顯著提升服務(wù)器的性能。 多線程編程的基本概念 多線
    的頭像 發(fā)表于 11-12 14:16 ?890次閱讀

    支付寶與華為終端達(dá)成戰(zhàn)略合作

    近日,支付寶與華為終端正式宣布達(dá)成戰(zhàn)略合作,共同致力于鴻蒙生態(tài)與碰一下生態(tài)的深度融合與發(fā)展。
    的頭像 發(fā)表于 11-11 14:46 ?672次閱讀

    eBay攜手螞蟻國(guó)際旗下Antom,支付寶成eBay新支付選項(xiàng)

    近日,eBay宣布與螞蟻國(guó)際旗下的Antom達(dá)成合作,正式將支付寶納入其支付選項(xiàng),為中國(guó)內(nèi)地買(mǎi)家提供更加便捷、安全的支付體驗(yàn)。 此次合作意味著,中國(guó)內(nèi)地消費(fèi)者在eBay平臺(tái)上購(gòu)物時(shí),可直接使用
    的頭像 發(fā)表于 11-11 13:56 ?1054次閱讀

    支付寶與華為終端達(dá)成戰(zhàn)略合作,共同推動(dòng)移動(dòng)支付進(jìn)入“碰時(shí)代”

    近日,支付寶與華為終端宣布了一項(xiàng)重要的戰(zhàn)略合作。此次合作將圍繞鴻蒙生態(tài)與支付寶的“碰一下”生態(tài)展開(kāi),旨在為用戶(hù)提供更加便捷、高效的移動(dòng)支付體驗(yàn)。 根據(jù)雙方簽署的戰(zhàn)略合作協(xié)議,華為將通過(guò)軟硬件的全面
    的頭像 發(fā)表于 11-10 11:16 ?1083次閱讀

    Spring事務(wù)實(shí)現(xiàn)原理

    作者:京東零售 范錫軍 1、引言 spring的spring-tx模塊提供了對(duì)事務(wù)管理支持,使用spring事務(wù)可以讓我們從復(fù)雜的事務(wù)處理中得到解脫,無(wú)需要去處理獲得連接、關(guān)閉連接、事務(wù)
    的頭像 發(fā)表于 11-08 10:10 ?1111次閱讀
    Spring<b class='flag-5'>事務(wù)</b>實(shí)現(xiàn)原理

    Python中多線程和多進(jìn)程的區(qū)別

    Python作為一種高級(jí)編程語(yǔ)言,提供了多種并發(fā)編程的方式,其中多線程與多進(jìn)程是最常見(jiàn)的兩種方式之一。在本文中,我們將探討Python中多線程與多進(jìn)程的概念、區(qū)別以及如何使用線程池與進(jìn)程池來(lái)提高并發(fā)執(zhí)行效率。
    的頭像 發(fā)表于 10-23 11:48 ?913次閱讀
    Python中<b class='flag-5'>多線程</b>和多進(jìn)程的區(qū)別

    ESP32會(huì)不會(huì)有多線程問(wèn)題,需要加鎖嗎?

    ESP32會(huì)不會(huì)有多線程問(wèn)題,需要加鎖嗎
    發(fā)表于 07-19 08:05

    復(fù)旦微電 Boost Tag 芯片助力支付寶NFC支付

    隨著技術(shù)的進(jìn)步,移動(dòng)支付技術(shù)正快速更新迭代。近日,支付寶正式推出NFC支付功能,用戶(hù)只需將手機(jī)“碰一碰”收銀臺(tái)NFC支付設(shè)備,即可輕松完成支付
    的頭像 發(fā)表于 07-12 18:02 ?3084次閱讀

    歡創(chuàng)播報(bào) 支付寶“碰一下”正式發(fā)布

    1 支付寶“碰一下”正式發(fā)布 近日,在支付寶開(kāi)放日上,支付寶宣布升級(jí)條碼支付體驗(yàn),推出“支付寶碰一下”,用戶(hù)無(wú)需展示付款碼,解鎖手機(jī)碰一下商
    的頭像 發(fā)表于 07-11 11:32 ?1383次閱讀
    歡創(chuàng)播報(bào)  <b class='flag-5'>支付寶</b>“碰一下”正式發(fā)布

    多線程設(shè)計(jì)模式到對(duì) CompletableFuture 的應(yīng)用

    最近在開(kāi)發(fā) 延保服務(wù) 頻道頁(yè)時(shí),為了提高查詢(xún)效率,使用到了多線程技術(shù)。為了對(duì)多線程方案設(shè)計(jì)有更加充分的了解,在業(yè)余時(shí)間讀完了《圖解 Java 多線程設(shè)計(jì)模式》這本書(shū),覺(jué)得收獲良多。本篇文章將介紹其中
    的頭像 發(fā)表于 06-26 14:18 ?613次閱讀
    從<b class='flag-5'>多線程</b>設(shè)計(jì)模式到對(duì) CompletableFuture 的應(yīng)用

    智能手機(jī)移動(dòng)支付功能的最佳選擇TG2520SMN溫補(bǔ)晶振X1G005421030427

    近年來(lái),中國(guó)最大的變化之一就是移動(dòng)支付的迅速普及,主要為兩大巨頭的較量“微信”“支付寶”.即是馬云和馬化騰之間的較量,這兩位馬家人是現(xiàn)在中國(guó)的傳奇人物。微信和支付寶為了搶占市場(chǎng)各顯神通,祭出微信鼓勵(lì)
    的頭像 發(fā)表于 06-20 14:40 ?602次閱讀
    智能手機(jī)移動(dòng)<b class='flag-5'>支付</b>功能的最佳選擇TG2520SMN溫補(bǔ)晶振X1G005421030427

    利用Swap模式實(shí)現(xiàn)代碼操作

    前面介紹了MCUboot的基礎(chǔ)知識(shí),您可通過(guò)上方鏈接回顧歷史文章,上次介紹了Swap模式,本次著重介紹利用Swap模式實(shí)現(xiàn)代碼操作。在某些應(yīng)用場(chǎng)景中,可能新版本的Firmware存在bug而需要返回至上一次的固件。
    的頭像 發(fā)表于 06-19 15:45 ?1730次閱讀
    利用Swap模式實(shí)現(xiàn)代碼<b class='flag-5'>回</b><b class='flag-5'>滾</b>操作