最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

反對使用Spring封裝的多線程類原因

 更新時間:2022年05月16日 10:16:16   作者:??小姐姐味道????  
這篇文章主要介紹了反對使用Spring封裝的多線程類原因,文章圍繞主題展開詳細內容介紹,具有一定的參考價值,需要的小伙伴可以參考一下

前言:

工作總難免會遇到被故障所驅使,其實是開啟了線程池的暴力使用模式

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

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

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

1.Spring的異步代碼

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

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

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

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

@SpringBootApplication
@EnableAsync
public?class?DemoApplication?{

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

@Component
public?class?AsyncService?{
????@Async
????public?void?async(){
????????try?{
????????????Thread.sleep(1000);
????????????System.out.println(Thread.currentThread());
????????}catch?(Exception?ex){
????????????ex.printStackTrace();
????????}
????}
}

然后,做一個對應的test接口,訪問時會調用這個async方法。

@ResponseBody
@GetMapping("test")
public?void?test(){
????service.async();
}

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

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

throw?new?TaskRejectedException("Executor?["?+?executor?+?"]?did?not?accept?task:?"?+?task,?var4);

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

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

2.是SpringBoot救了你

SpringBoot是個好東西。

在TaskExecutionAutoConfiguration中,通過生成ThreadPoolTaskExecutor的Bean,來提供默認的Executor。

@ConditionalOnMissingBean({Executor.class})
public?ThreadPoolTaskExecutor?applicationTaskExecutor(TaskExecutorBuilder?builder)?{
????return?builder.build();
}

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

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

@Override
@Nullable
protected?Executor?getDefaultExecutor(@Nullable?BeanFactory?beanFactory)?{
?Executor?defaultExecutor?=?super.getDefaultExecutor(beanFactory);
?return?(defaultExecutor?!=?null???defaultExecutor?:?new?SimpleAsyncTaskExecutor());
}

這就是Spring大仙所干的事。

SimpleAsyncTaskExecutor類設計的非常操蛋,因為它每執(zhí)行一次,都會創(chuàng)建一個單獨的線程,根本沒有共用線程池。比如你的TPS是1000,異步執(zhí)行了任務,那么你每秒將會生成1000個線程!

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

protected?void?doExecute(Runnable?task)?{
?Thread?thread?=?(this.threadFactory?!=?null???this.threadFactory.newThread(task)?:?createThread(task));
?thread.start();
}

3.End

明眼人一看,這種使用new線程的處理方式將會是非常可怕的。但就拿Spring本身來說,引用SimpleAsyncTaskExecutor這個類的地方還不少,包括比較流行的AsyncRestTemplate。

這暴露了很多風險,尤其是竟然在這些列表中看到了redis的身影。這個類的設計,使得任務的執(zhí)行變的非常的不可控。

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

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

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

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

就連原生的線程池我們還沒搞明白呢,你還給包了一層,這是方便我們甩鍋??!

到此這篇關于反對使用Spring封裝的多線程類原因的文章就介紹到這了,更多相關Spring封裝多線程類內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

阿尔山市| 彭山县| 涿鹿县| 阳东县| 石台县| 景宁| 江西省| 抚顺县| 马边| 栾川县| 乌海市| 新宁县| 永吉县| 乌什县| 呼玛县| 平罗县| 金乡县| 富裕县| 五莲县| 沙坪坝区| 涞源县| 顺昌县| 美姑县| 衢州市| 若羌县| 如皋市| 泗阳县| 南康市| 轮台县| 岫岩| 星座| 东港市| 迁安市| 葵青区| 澎湖县| 聂拉木县| 陵水| 镇坪县| 昌都县| 荔浦县| 济宁市|