Springboot 異步任務(wù)使用
1、在調(diào)用異步方法類上或者在啟動(dòng)類(有@SpringBootApplication的類)上增加注解:
@EnableAsync
2、在要開啟異步任務(wù)的方法上增加注解:@Async
Spring默認(rèn)線程池?SimpleAsyncTaskExecutor
Spring異步線程池的接口類是TaskExecutor,本質(zhì)還是java.util.concurrent.Executor,沒有配置的情況下,默認(rèn)使用的是?SimpleAsyncTaskExecutor。
注意點(diǎn)
關(guān)于注解失效需要注意以下幾點(diǎn)
注解的方法必須是public方法
方法一定要從另一個(gè)類中調(diào)用,也就是從類的外部調(diào)用,類的內(nèi)部調(diào)用是無效的,因?yàn)锧Transactional和@Async注解的實(shí)現(xiàn)都是基于Spring的AOP,而AOP的實(shí)現(xiàn)是基于動(dòng)態(tài)代理模式實(shí)現(xiàn)的。那么注解失效的原因就很明顯了,有可能因?yàn)檎{(diào)用方法的是對象本身而不是代理對象,因?yàn)闆]有經(jīng)過Spring容器。
異步方法使用注解@Async的返回值只能為void或者Future
解決辦法:
如果要使同一個(gè)類中的方法之間調(diào)用也被攔截,需要使用spring容器中的實(shí)例對象,而不是使用默認(rèn)的this,因?yàn)橥ㄟ^bean實(shí)例的調(diào)用才會被spring的aop攔截
本例使用方法:AsyncService asyncService = context.getBean(AsyncService.class); 然后使用這個(gè)引用調(diào)用本地的方法即可達(dá)到被攔截的目的。
為什么要使用自定義線程池
如果不自定義異步方法的線程池默認(rèn)使用SimpleAsyncTaskExecutor。SimpleAsyncTaskExecutor:不是真的線程池,這個(gè)類不重用線程,每次調(diào)用都會創(chuàng)建一個(gè)新的線程。并發(fā)大的時(shí)候會產(chǎn)生嚴(yán)重的性能問題。
拓展
內(nèi)存溢出的三種類型
第一種OutOfMemoryError: PermGen space,發(fā)生這種問題的原因是程序中使用了大量的jar或class
第二種OutOfMemoryError: Java heap space,發(fā)生這種問題的原因是java虛擬機(jī)創(chuàng)建的對象太多
第三種OutOfMemoryError:unable to create new native thread,創(chuàng)建線程數(shù)量太多,占用內(nèi)存過大
線程池拒絕策略
rejectedExectutionHandler參數(shù)字段用于配置絕策略,常用拒絕策略如下
AbortPolicy:用于被拒絕任務(wù)的處理程序,它將拋出RejectedExecutionException
CallerRunsPolicy:用于被拒絕任務(wù)的處理程序,它直接在execute方法的調(diào)用線程中運(yùn)行被拒絕的任務(wù)。
DiscardOldestPolicy:用于被拒絕任務(wù)的處理程序,它放棄最舊的未處理請求,然后重試execute。
DiscardPolicy:用于被拒絕任務(wù)的處理程序,默認(rèn)情況下它將丟棄被拒絕的任務(wù)。