Springboot之@Async不執(zhí)行原因及分析
背景
項目中有一個異步方法允許一段時間后就不再執(zhí)行了。該異步方法是使用@Async注解的。
分析原因
1.業(yè)務(wù)場景用了@Async注解的方法,且沒有使用自定義線程池。
2.ThreadPoolTaskExecutor是springboot提供的默認(rèn)線程池 。
也就是說如果沒有自定義線程池,那么會自動裝配這個默認(rèn)的。
In the absence of an Executor bean in the context, Spring Boot auto-configures a ThreadPoolTaskExecutor with sensible defaults that can be automatically associated to asynchronous task execution (@EnableAsync) and Spring MVC asynchronous request processing.
3.ThreadPoolTaskExecutor的默認(rèn)參數(shù)是由TaskExecutionProperties控制的。
默認(rèn)核心線程是8,線程prefix是 “task-”。
搜索線程dump,有8個異步任務(wù)已經(jīng)耗盡了線程池,且執(zhí)行沒有停止的跡象。
構(gòu)造默認(rèn)線程池方法
org.springframework.boot.task.TaskExecutorBuilder#configure
4.如果該線程池被耗盡,則所有任務(wù)將會在線程池的隊列中等待,而默認(rèn)隊列大小是Integer.MAX_VALUE
5.一方面要調(diào)整業(yè)務(wù)代碼,使用默認(rèn)線程池;另一方面也可以暫時增加默認(rèn)線程池大小緩解
@Async使用總結(jié)
1、 非必須不使用異步。如果是核心業(yè)務(wù)包含事務(wù)處理,先同步記錄數(shù)據(jù),再異步發(fā)起。防止直接發(fā)起后異步?jīng)]被調(diào)度到服務(wù)關(guān)閉,造成數(shù)據(jù)丟失
2、 核心業(yè)務(wù)必須使用自定義線程池,防止默認(rèn)異步線程池阻塞,也方便通過線程池監(jiān)控核心執(zhí)行情況
3、 簡單業(yè)務(wù)場景使用默認(rèn)線程池時,避免操作長時間過長占用默認(rèn)線程池,影響Spring以及別的框架組件異步任務(wù)執(zhí)行
4、 @Async可能失效的原因
- a) @SpringBootApplication啟動類當(dāng)中沒有添加@EnableAsync注解。
- b) 異步方法使用注解@Async的返回值只能為void或者Future。
- c) 沒有走Spring的代理類。因為@Transactional和@Async注解的實現(xiàn)都是基于Spring的AOP,而AOP的實現(xiàn)是基于動態(tài)代理模式實現(xiàn)的。那么注解失效的原因就很明顯了,有可能因為調(diào)用方法的是對象本身而不是代理對象,因為沒有經(jīng)過Spring容器管理。
@Async失效解決方法
- a) 注解的方法必須是public方法。
- b) 注解的方法不要定義為static
- c) 方法一定要從另一個類中調(diào)用,也就是從類的外部調(diào)用,類的內(nèi)部調(diào)用是無效的。
- d) 如果需要從類的內(nèi)部調(diào)用,需要先獲取其代理類。
如果該線程池被耗盡,則所有任務(wù)將會在線程池的隊列中等待,而默認(rèn)隊列大小是Integer.MAX_VALUE
一方面要調(diào)整業(yè)務(wù)代碼,使用默認(rèn)線程池;另一方面也可以暫時增加默認(rèn)線程池大小緩解
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring中@Value讀取properties作為map或list的操作
這篇文章主要介紹了Spring中@Value讀取properties作為map或list的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07Java Swing中的工具欄(JToolBar)和分割面版(JSplitPane)組件使用案例
這篇文章主要介紹了Java Swing中的工具欄(JToolBar)和分割面版(JSplitPane)組件使用案例,本文直接給出代碼實例和效果截圖,需要的朋友可以參考下2014-10-10淺談java二進(jìn)制、十進(jìn)制、十六進(jìn)制、字符串之間的相互轉(zhuǎn)換
下面小編就為大家?guī)硪黄獪\談二進(jìn)制、十進(jìn)制、十六進(jìn)制、字符串之間的相互轉(zhuǎn)換。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考,一起跟隨小編過來看看吧2016-06-06詳解SpringMVC的攔截器鏈實現(xiàn)及攔截器鏈配置
攔截器(Interceptor)是一種動態(tài)攔截方法調(diào)用的機(jī)制,在SpringMVC中動態(tài)攔截控制器方法的執(zhí)行。本文將詳細(xì)講講SpringMVC中攔截器參數(shù)及攔截器鏈配置,感興趣的可以嘗試一下2022-08-08詳解在idea 中使用Mybatis Generator逆向工程生成代碼
這篇文章主要介紹了在idea 中使用Mybatis Generator逆向工程生成代碼,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-12-12