springboot中如何使用@Async方法
一.在啟動(dòng)類上加上 啟動(dòng)注解 @EnableAsync
二. 在需要進(jìn)行異步處理的方法上加上注解@ Async
注意事項(xiàng):
注解的方法 必須是public方法,因?yàn)樵撟⒔獠捎玫氖莿?dòng)態(tài)代理的方式
無(wú)論該方法的返回值是什么,被@Async注解的方法必定是Null
在方法內(nèi)不要遞歸調(diào)用,否則無(wú)效
三.自定義異步采用的線程池
當(dāng)我們沒有自定義時(shí),springboot是怎么樣采用默認(rèn)配置的?
翻譯:當(dāng)spring執(zhí)行這個(gè)方法時(shí),默認(rèn)會(huì)搜索關(guān)聯(lián)的線程池定義。
上下文中唯一的 Spring 框架 TaskExecutor bean 或名為“taskExecutor”的 Executor bean。
如果這兩個(gè)都不能解析,默認(rèn)會(huì)使用spring框架SimpleAsyncTaskExecutor來(lái)處理異步方法的執(zhí)行。
使用上面的步驟,可以直接使用異步注解了,但是需要注意的是,異步所需的線程池采用的是springboot框架默認(rèn)的線程池,我們有時(shí)候還需要自定義線程池來(lái)限制并發(fā)線程數(shù)和最大隊(duì)列。
怎么配置異步功能的異步線程池?
法一. 實(shí)現(xiàn)配置類 AsyncConfigurer
@Configuration @EnableAsync public class BaseAsyncConfigurer implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心線程池?cái)?shù)量,方法: 返回可用處理器的Java虛擬機(jī)的數(shù)量。 executor.setCorePoolSize(Runtime.getRuntime().availableProcessors()); //最大線程數(shù)量 executor.setMaxPoolSize(Runtime.getRuntime().availableProcessors()*5); //線程池的隊(duì)列容量 executor.setQueueCapacity(Runtime.getRuntime().availableProcessors()*2); //線程名稱的前綴 executor.setThreadNamePrefix("this-excutor-"); // setRejectedExecutionHandler:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù) // CallerRunsPolicy:不在新線程中執(zhí)行任務(wù),而是由調(diào)用者所在的線程來(lái)執(zhí)行 //executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.initialize(); return executor; } /*異步任務(wù)中異常處理*/ @Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return (Throwable ex, Method method, Object... params)->{ //todo 異步方法異常處理 System.out.println("class#method: " + method.getDeclaringClass().getName() + "#" + method.getName()); System.out.println("type : " + ex.getClass().getName()); System.out.println("exception : " + ex.getMessage()); }; } }
實(shí)現(xiàn)了這個(gè)接口過后,在使用@Async時(shí)就會(huì)自動(dòng)使用我們自定義的線程池getAsyncExecutor了。
法二. 自定義一個(gè)線程池bean,在使用@Async注解時(shí)指定線程池
@Bean("threadPoolTaskExecutor") public TaskExecutor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(20); executor.setMaxPoolSize(1000); executor.setWaitForTasksToCompleteOnShutdown(true); executor.setThreadNamePrefix("Async-"); return executor; }
使用注解@Async(“threadPoolTaskExecutor”) ,相當(dāng)于在一個(gè)項(xiàng)目中,不同方法上面的@Async可以使用不同的線程池
總結(jié)
一般情況下,建議手動(dòng)實(shí)現(xiàn)AsyncConfigurer來(lái)自定義線程池。
如果某些方法需要使用其他的線程池,就使用bean添加一個(gè)線程池,并在@Async的value值進(jìn)行指定線程池。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java RSA加密工具類的設(shè)計(jì)與實(shí)現(xiàn)詳解
RSA算法是一種常用的非對(duì)稱加密算法,這篇文章主要為大家詳細(xì)介紹了如何通過Java編寫一個(gè)RSA加密工具類,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2025-02-02Java RocketMQ 路由注冊(cè)與刪除的實(shí)現(xiàn)
這篇文章主要介紹了Java RocketMQ 路由注冊(cè)與刪除的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11SpringBoot集成MyBatisPlus+MySQL的實(shí)現(xiàn)
MybatisPlus是國(guó)產(chǎn)的第三方插件, 它封裝了許多常用的CURDapi,免去了我們寫mapper.xml的重復(fù)勞動(dòng),本文主要介紹了SpringBoot集成MyBatisPlus+MySQL的實(shí)現(xiàn),感興趣的可以了解一下2023-10-10java實(shí)現(xiàn)周期性執(zhí)行(定時(shí)任務(wù))
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)周期性執(zhí)行定時(shí)任務(wù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-09-09Java并發(fā)編程示例(一):線程的創(chuàng)建和執(zhí)行
這篇文章主要介紹了Java并發(fā)編程示例(一):線程的創(chuàng)建和執(zhí)行,本文是系列文章的第一篇,需要的朋友可以參考下2014-12-12Java并發(fā)編程之關(guān)鍵字volatile的深入解析
提高java的并發(fā)編程,就不得不提volatile關(guān)鍵字,不管是在面試還是實(shí)際開發(fā)中volatile都是一個(gè)應(yīng)該掌握的技能,這篇文章主要給大家介紹了關(guān)于Java并發(fā)編程之關(guān)鍵字volatile的相關(guān)資料,需要的朋友可以參考下2021-09-09