衡阳派盒市场营销有限公司

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

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

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

強(qiáng)烈反對(duì)使用Spring封裝的多線程類

PLC工控專欄 ? 來源:加密狗破解 ? 作者:加密狗破解 ? 2022-02-22 08:58 ? 次閱讀

在很久很久之前,我有一段痛苦的記憶。那種被故障所驅(qū)使的感覺,在我腦海里久久無法驅(qū)散。

原因無它,有小伙伴開啟了線程池的暴力使用模式。沒錯(cuò),就是下面這篇文章。

奪命故障 ! 炸出了投資人!

我有必要簡(jiǎn)單的復(fù)述一下。其主要原因,就是開發(fā)人員,在每一次方法調(diào)用里,都創(chuàng)建了一個(gè)單獨(dú)的線程池去處理。這樣的話,如果請(qǐng)求量一增加,整個(gè)操作系統(tǒng)的壓力就會(huì)耗盡,最終所有的業(yè)務(wù)都無法響應(yīng)。

強(qiáng)烈反對(duì)使用Spring封裝的多線程類

我一直認(rèn)為這是一個(gè)非常偶發(fā)的低級(jí)錯(cuò)誤,發(fā)生頻率非常的低。但隨著這樣的故障越來越多,xjjdog認(rèn)識(shí)到這是一個(gè)普遍的現(xiàn)象。

以異步性能優(yōu)化為目的,反而帶來的整體業(yè)務(wù)不可用的結(jié)果,是非常打臉的一種優(yōu)化。

1.Spring的異步代碼

Spring作為Java屆的杠把子框架,其過度封裝的API深得開發(fā)人員的喜愛。根據(jù)語義化編程的邏輯,只要某些關(guān)鍵字在語言層面上過得去,我們就可以把它給加上去。比如@Async注解。

我永遠(yuǎn)想不通是什么給了開發(fā)人員勇氣,去加上這個(gè)@Async注解,因?yàn)檫@種涉及到多線程的東西,即使是自己去創(chuàng)建線程,也是心懷敬畏,唯恐?jǐn)_了操作系統(tǒng)的安寧。@Async這樣的黑盒,真的可以那么順暢的使用么?

我們不妨debug一下代碼,讓子彈飛一會(huì)兒。

首先,生成一個(gè)小小的項(xiàng)目,然后在主類上加上必須的注解。嗯,別忘了這一環(huán),否則你后面加的注解將沒什么用處。

@SpringBootApplication
@EnableAsync
publicclassDemoApplication{

復(fù)制代碼

創(chuàng)造一個(gè)帶@Async注解的方法。

@Component
publicclassAsyncService{
@Async
publicvoidasync(){
try{
Thread.sleep(1000);
System.out.println(Thread.currentThread());
}catch(Exceptionex){
ex.printStackTrace();
}
}
}

復(fù)制代碼

然后,做一個(gè)對(duì)應(yīng)的test接口,訪問時(shí)會(huì)調(diào)用這個(gè)async方法。

@ResponseBody
@GetMapping("test")
publicvoidtest(){
service.async();
}

復(fù)制代碼

訪問時(shí),直接打個(gè)斷點(diǎn),即可獲取執(zhí)行異步線程的線程池。

強(qiáng)烈反對(duì)使用Spring封裝的多線程類

可以看到,異步任務(wù)使用了一個(gè)線程池,它的corePoolSize=8, 阻塞隊(duì)列采用了無界隊(duì)列LinkedBlockingQueue。一旦采用了這樣的組合,最大線程數(shù)就會(huì)形同虛設(shè),因?yàn)槌?個(gè)線程的任務(wù),將全部會(huì)被放到無界隊(duì)列里。使得下面的代碼變成了擺設(shè)。

thrownewTaskRejectedException("Executor["+executor+"]didnotaccepttask:"+task,var4);

復(fù)制代碼

如果你的訪問量非常大,這些任務(wù)將全部堆積在LinkedBlockingQueue里。情況好一點(diǎn)的,這些任務(wù)的執(zhí)行會(huì)變得延遲很大;情況壞一點(diǎn)的,任務(wù)太多將直接造成內(nèi)存溢出OOM!

你可能會(huì)說,我可以自己指定另外一個(gè)ThreadPoolExceute,然后使用@Async注解來聲明啊。說這話的同學(xué),一定是能力比較強(qiáng),或者Review的代碼比較少,沒有經(jīng)過豬隊(duì)友的洗禮。

2.是SpringBoot救了你

SpringBoot是個(gè)好東西。

在TaskExecutionAutoConfiguration中,通過生成ThreadPoolTaskExecutor的Bean,來提供默認(rèn)的Executor。

@ConditionalOnMissingBean({Executor.class})
publicThreadPoolTaskExecutorapplicationTaskExecutor(TaskExecutorBuilderbuilder){
returnbuilder.build();
}

復(fù)制代碼

也就是我們上面所說的那個(gè)。如果沒有SpringBoot的助力,Spring將默認(rèn)使用SimpleAsyncTaskExecutor。

參見org.springframework.aop.interceptor.AsyncExecutionInterceptor。

@Override
@Nullable
protectedExecutorgetDefaultExecutor(@NullableBeanFactorybeanFactory){
ExecutordefaultExecutor=super.getDefaultExecutor(beanFactory);
return(defaultExecutor!=null?defaultExecutor:newSimpleAsyncTaskExecutor());
}

復(fù)制代碼

這就是Spring大仙所干的事。

SimpleAsyncTaskExecutor類設(shè)計(jì)的非常操蛋,因?yàn)樗繄?zhí)行一次,都會(huì)創(chuàng)建一個(gè)單獨(dú)的線程,根本沒有共用線程池。比如你的TPS是1000,異步執(zhí)行了任務(wù),那么你每秒將會(huì)生成1000個(gè)線程!

這明顯是想要累死操作系統(tǒng)的節(jié)奏。

protectedvoiddoExecute(Runnabletask){
Threadthread=(this.threadFactory!=null?this.threadFactory.newThread(task):createThread(task));
thread.start();
}

復(fù)制代碼

3.End

明眼人一看,這種使用new線程的處理方式將會(huì)是非??膳碌?。但就拿Spring本身來說,引用SimpleAsyncTaskExecutor這個(gè)類的地方還不少,包括比較流行的AsyncRestTemplate。

強(qiáng)烈反對(duì)使用Spring封裝的多線程類

這暴露了很多風(fēng)險(xiǎn),尤其是竟然在這些列表中看到了redis的身影。這個(gè)類的設(shè)計(jì),使得任務(wù)的執(zhí)行變的非常的不可控。

看這個(gè)API,我感覺Spring是進(jìn)入了設(shè)計(jì)的魔怔狀態(tài)。

這個(gè)東西的隱藏bug可能還會(huì)更深!比如org.springframework.context.event.EventListener注解,用于實(shí)現(xiàn)DDD那套所謂的事件驅(qū)動(dòng)模式,有不少框架直接set了AsyncRestTemplate,那么就等死吧。

趕緊把SimpleAsyncTaskExecutor加入你的API黑名單,或者埋坑清單吧!

創(chuàng)建線程有那么難么?需要使用Spring創(chuàng)建的線程?有時(shí)候我實(shí)在是想不通,暴露出這樣的接口目的是為了什么。

審核編輯:湯梓紅

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

    關(guān)注

    127

    文章

    7997

    瀏覽量

    143416
  • 多線程
    +關(guān)注

    關(guān)注

    0

    文章

    278

    瀏覽量

    20075
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    340

    瀏覽量

    14392
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    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 ?469次閱讀

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

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

    LWIP多線程強(qiáng)烈建議開啟LWIP_ASSERT_CORE_LOCKED宏,這個(gè)在RTT里面要怎么實(shí)現(xiàn)?

    LWIP多線程強(qiáng)烈建議開啟LWIP_ASSERT_CORE_LOCKED宏,這個(gè)在RTT里面要怎么實(shí)現(xiàn),之前參考網(wǎng)上代碼,這樣寫,壓力測(cè)試下有概率斷言失敗 extern sys_mutex_t
    發(fā)表于 07-25 06:27

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

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

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

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

    bootloader開多線程做引導(dǎo)程序,跳app初始化后直接進(jìn)hardfualt,為什么?

    如標(biāo)題,想做一個(gè)遠(yuǎn)程升級(jí)的項(xiàng)目,bootloader引導(dǎo)區(qū)域和app都是開多線程跑的,就是自己寫了個(gè)小的任務(wù)調(diào)度器,沒什么功能主要是想讓程序快速的響應(yīng),延時(shí)不會(huì)對(duì)其他程序造成堵塞,程序測(cè)試
    發(fā)表于 04-18 06:07

    鴻蒙OS開發(fā)實(shí)例:【ArkTS多線程CPU密集型任務(wù)TaskPool】

    CPU密集型任務(wù)是指需要占用系統(tǒng)資源處理大量計(jì)算能力的任務(wù),需要長(zhǎng)時(shí)間運(yùn)行,這段時(shí)間會(huì)阻塞線程其它事件的處理,不適宜放在主線程進(jìn)行。例如圖像處理、視頻編碼、數(shù)據(jù)分析等。 基于多線程并發(fā)機(jī)制處理CPU密集型任務(wù)可以提高CPU
    的頭像 發(fā)表于 04-01 22:25 ?901次閱讀
    鴻蒙OS開發(fā)實(shí)例:【ArkTS<b class='flag-5'>類</b>庫<b class='flag-5'>多線程</b>CPU密集型任務(wù)TaskPool】

    鴻蒙OS開發(fā)實(shí)例:【ArkTS多線程I/O密集型任務(wù)開發(fā)】

    使用異步并發(fā)可以解決單次I/O任務(wù)阻塞的問題,但是如果遇到I/O密集型任務(wù),同樣會(huì)阻塞線程中其它任務(wù)的執(zhí)行,這時(shí)需要使用多線程并發(fā)能力來進(jìn)行解決。 I/O密集型任務(wù)的性能重點(diǎn)通常不在于CPU
    的頭像 發(fā)表于 04-01 16:32 ?586次閱讀
    鴻蒙OS開發(fā)實(shí)例:【ArkTS<b class='flag-5'>類</b>庫<b class='flag-5'>多線程</b>I/O密集型任務(wù)開發(fā)】

    鴻蒙APP開發(fā):【ArkTS多線程】TaskPool和Worker的對(duì)比

    TaskPool(任務(wù)池)和Worker的作用是為應(yīng)用程序提供一個(gè)多線程的運(yùn)行環(huán)境,用于處理耗時(shí)的計(jì)算任務(wù)或其他密集型任務(wù)??梢杂行У乇苊膺@些任務(wù)阻塞主線程,從而最大化系統(tǒng)的利用率,降低整體資源消耗,并提高系統(tǒng)的整體性能。
    的頭像 發(fā)表于 03-26 22:09 ?710次閱讀
    鴻蒙APP開發(fā):【ArkTS<b class='flag-5'>類</b>庫<b class='flag-5'>多線程</b>】TaskPool和Worker的對(duì)比

    鴻蒙原生應(yīng)用開發(fā)-ArkTS語言基礎(chǔ)多線程TaskPool和Worker的對(duì)比(二)

    TaskPool運(yùn)作機(jī)制 圖1 TaskPool運(yùn)作機(jī)制示意圖 TaskPool支持開發(fā)者在主線程封裝任務(wù)拋給任務(wù)隊(duì)列,系統(tǒng)選擇合適的工作線程,進(jìn)行任務(wù)的分發(fā)及執(zhí)行,再將結(jié)果返回給主線程
    發(fā)表于 03-26 15:25

    鴻蒙原生應(yīng)用開發(fā)-ArkTS語言基礎(chǔ)多線程TaskPool和Worker的對(duì)比(一)

    TaskPool(任務(wù)池)和Worker的作用是為應(yīng)用程序提供一個(gè)多線程的運(yùn)行環(huán)境,用于處理耗時(shí)的計(jì)算任務(wù)或其他密集型任務(wù)。可以有效地避免這些任務(wù)阻塞主線程,從而最大化系統(tǒng)的利用率,降低整體資源消耗
    發(fā)表于 03-25 14:11

    鴻蒙原生應(yīng)用開發(fā)-ArkTS語言基礎(chǔ)多線程I/O密集型任務(wù)開發(fā)

    使用異步并發(fā)可以解決單次I/O任務(wù)阻塞的問題,但是如果遇到I/O密集型任務(wù),同樣會(huì)阻塞線程中其它任務(wù)的執(zhí)行,這時(shí)需要使用多線程并發(fā)能力來進(jìn)行解決。 I/O密集型任務(wù)的性能重點(diǎn)通常不在于CPU的處理
    發(fā)表于 03-21 14:57

    java實(shí)現(xiàn)多線程的幾種方式

    了多種實(shí)現(xiàn)多線程的方式,本文將詳細(xì)介紹以下幾種方式: 1.繼承Thread 2.實(shí)現(xiàn)Runnable接口 3.Callable和Future 4.線程池 5.Java 8中
    的頭像 發(fā)表于 03-14 16:55 ?786次閱讀

    AT socket可以多線程調(diào)用嗎?

    請(qǐng)問AT socket 可以多線程調(diào)用嗎? 有互鎖機(jī)制嗎,還是要自己做互鎖。
    發(fā)表于 03-01 08:22

    ArkTS語言基礎(chǔ)庫-解析

    ArkTS語言基礎(chǔ)庫是HarmonyOS系統(tǒng)上為應(yīng)用開發(fā)者提供的常用基礎(chǔ)能力,主要包含能力如下圖所示。 圖1 ArkTS語言基礎(chǔ)庫能力示意圖 提供[異步并發(fā)和多線程并發(fā)]的能力。 支持
    發(fā)表于 02-20 16:44
    百家乐官网的玩法技巧和规则| 风水罗盘24方位| bet365娱乐场| 百家乐看大路| 百家乐官网大小点桌子| 大发888在线娱乐城| 百家乐园云鼎娱乐网| 试玩百家乐官网的玩法技巧和规则| 百家乐官网如何投注法| 大发888博彩官方下载| 网上百家乐是假还是真的| 澳门百家乐官网官网| 免佣百家乐官网的玩法| 蒙山县| 456棋牌官网| 威尼斯人娱乐城网络博彩| 百家乐概率统计| 国美百家乐官网的玩法技巧和规则| 百家乐官网在线投注系统| 申城棋牌2.0| 全讯网高手世家| 百家乐1元投注| 百家乐投注双赢技巧| 免费百家乐官网追号软件| 百家乐官网游戏作弊| 乐百家乐官网彩现金开户| 日博娱乐城| bet365高尔夫娱乐场| 大发888线上娱乐城百家乐| 百家乐技巧娱乐博彩| 百家乐赢家公式| 澳门百家乐必杀技| 赌百家乐的高手| 狮威百家乐官网娱乐城| 百家乐官网大路小路三珠路| 百家乐官网有多少种游戏| 百家乐官网娱乐城注册| 百家乐官网投注翻倍方法| 百家乐官网视频游戏界面| 网上百家乐官网心得| 星河百家乐官网现金网|