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

SpringBoot異步使用@Async的原理以及線程池配置詳解

 更新時(shí)間:2021年09月15日 11:13:09   作者:kenx  
在項(xiàng)目中當(dāng)訪問(wèn)其他人的接口較慢時(shí),不想程序一直卡在耗時(shí)任務(wù)上,想程序能夠并行執(zhí)行,我們可以使用多線程來(lái)并行的處理任務(wù),也可以使用spring提供的異步處理方式@Async,這篇文章主要給大家介紹了關(guān)于SpringBoot異步使用@Async的原理以及線程池配置的相關(guān)資料

前言

在實(shí)際項(xiàng)目開(kāi)發(fā)中很多業(yè)務(wù)場(chǎng)景需要使用異步去完成,比如消息通知,日志記錄,等非常常用的都可以通過(guò)異步去執(zhí)行,提高效率,那么在Spring框架中應(yīng)該如何去使用異步呢

使用步驟

完成異步操作一般有兩種,消息隊(duì)列MQ,和線程池處理ThreadPoolExecutor

而在Spring4中提供的對(duì)ThreadPoolExecutor封裝的線程池ThreadPoolTaskExecutor,直接使用注解啟用@Async,這個(gè)注解讓我們?cè)谑褂肧pring完成異步操作變得非常方便

配置線程池類參數(shù)配置

自定義常量類

public class ConstantFiledUtil {
    public static final String AUTHORIZATION_TOKEN = "authorizationToken";
    /**
     * kmall線程池名稱
     */
    public static final String KMALL_THREAD_POOL = "KmallThreadPool";

    /**
     * kmall線程名稱前綴
     */
    public static final String KMALL_THREAD_NAME_PREFIX = "kmall-thread-";
}

配置線程池

@Configuration(proxyBeanMethods = false)
@EnableAsync //開(kāi)啟注解
public class KmallConfig {
  
  @Bean(ConstantFiledUtil.KMALL_THREAD_POOL)
    public ThreadPoolTaskExecutor FebsShiroThreadPoolTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         //配置核心線程數(shù)
        executor.setCorePoolSize(5);
        //配置最大線程數(shù)
        executor.setMaxPoolSize(20);
        //配置隊(duì)列大小
        executor.setQueueCapacity(200);
        //線程池維護(hù)線程所允許的空閑時(shí)間
        executor.setKeepAliveSeconds(30);
        //配置線程池中的線程的名稱前綴
        executor.setThreadNamePrefix(ConstantFiledUtil.KMALL_THREAD_NAME_PREFIX);
        //設(shè)置線程池關(guān)閉的時(shí)候等待所有任務(wù)都完成再繼續(xù)銷毀其他的Bean
        executor.setWaitForTasksToCompleteOnShutdown(true);
        //設(shè)置線程池中任務(wù)的等待時(shí)間,如果超過(guò)這個(gè)時(shí)候還沒(méi)有銷毀就強(qiáng)制銷毀,以確保應(yīng)用最后能夠被關(guān)閉,而不是阻塞住
        executor.setAwaitTerminationSeconds(60);
          // rejection-policy:當(dāng)pool已經(jīng)達(dá)到max size的時(shí)候,如何處理新任務(wù)
        // CALLER_RUNS:不在新線程中執(zhí)行任務(wù),而是由調(diào)用者所在的線程來(lái)執(zhí)行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //執(zhí)行初始化
        executor.initialize();
        return executor;
    }
   
}

注意這里需要通過(guò)@EnableAsync開(kāi)啟異步否則無(wú)效

自定義線程任務(wù)

public interface ILogService extends IService<Log> {

    /**
     * 分頁(yè)搜索查詢?nèi)罩拘畔?
     * @param logParams
     * @return
     */
    IPage getSearchLogByPage(SearchLogParams logParams);

    /**
     * 保存日志
     *
     * @param logSubject
     */
    @Async
    void saveLog(LogSubject logSubject);
}

在需要異步執(zhí)行的接口,或者方法上加上@Async注解此方法就是異步方法,在主程序中調(diào)用的化,就是異步方式單獨(dú)線程執(zhí)行

此注解表明saveLog方法進(jìn)入的線程池是KmallThreadPool方法創(chuàng)建的。

我們也可以單獨(dú)指定方法名稱@Async("saveLogs")

這樣在進(jìn)行日記記錄的時(shí)候就是單獨(dú)線程執(zhí)行每次請(qǐng)求都快速響應(yīng)了,而耗時(shí)的操作都留給線程池中的線程去異步執(zhí)行

總結(jié)

Spring中用@Async注解標(biāo)記的方法,稱為異步方法。在spring boot應(yīng)用中使用@Async很簡(jiǎn)單:

  1. 調(diào)用異步方法類上或者啟動(dòng)類加上注解@EnableAsync
  2. 在需要被異步調(diào)用的方法外加上@Async
  3. 所使用的@Async注解方法的類對(duì)象應(yīng)該是Spring容器管理的bean對(duì)象;

注意同一個(gè)類里面調(diào)用異步方法不生效:原因默認(rèn)類內(nèi)的方法調(diào)用不會(huì)被aop攔截,即調(diào)用方和被調(diào)用方是在同一個(gè)類中,是無(wú)法產(chǎn)生切面的,該對(duì)象沒(méi)有被Spring容器管理。即@Async方法不生效

解決辦法:

如果要使同一個(gè)類中的方法之間調(diào)用也被攔截,需要使用spring容器中的實(shí)例對(duì)象,而不是使用默認(rèn)的this,因?yàn)橥ㄟ^(guò)bean實(shí)例的調(diào)用才會(huì)被spring的aop攔截

本例使用方法:AsyncService asyncService = context.getBean(AsyncService.class); 然后使用這個(gè)引用調(diào)用本地的方法即可達(dá)到被攔截的目的

備注:這種方法只能攔截protected,default,public方法,private方法無(wú)法攔截。這個(gè)是spring aop的一個(gè)機(jī)制。

原理刨析

異步方法返回類型只能有兩種:

  1. 當(dāng)返回類型為void的時(shí)候,方法調(diào)用過(guò)程產(chǎn)生的異常不會(huì)拋到調(diào)用者層面,可以通過(guò)注AsyncUncaughtExceptionHandler來(lái)捕獲此類異常
  2. 當(dāng)返回類型為Future的時(shí)候,方法調(diào)用過(guò)程產(chǎn)生的異常會(huì)拋到調(diào)用者層面

注意如果不自定義異步方法的線程池默認(rèn)使用SimpleAsyncTaskExecutor。SimpleAsyncTaskExecutor:不是真的線程池,這個(gè)類不重用線程,每次調(diào)用都會(huì)創(chuàng)建一個(gè)新的線程。并發(fā)大的時(shí)候會(huì)產(chǎn)生嚴(yán)重的性能問(wèn)題。

Spring異步線程池接口 TaskExecutor

看源碼可知

@FunctionalInterface
public interface TaskExecutor extends Executor {
    void execute(Runnable var1);
}

它的實(shí)先類有很多如下:

  1. SimpleAsyncTaskExecutor:不是真的線程池,這個(gè)類不重用線程,每次調(diào)用都會(huì)創(chuàng)建一個(gè)新的線程。
  2. SyncTaskExecutor:這個(gè)類沒(méi)有實(shí)現(xiàn)異步調(diào)用,只是一個(gè)同步操作。只適用于不需要多線程的地方
  3. ConcurrentTaskExecutor:Executor的適配類,不推薦使用。如果ThreadPoolTaskExecutor不滿足要求時(shí),才用考慮使用這個(gè)類
  4. SimpleThreadPoolTaskExecutor:是Quartz的SimpleThreadPool的類。線程池同時(shí)被quartz和非quartz使用,才需要使用此類
  5. ThreadPoolTaskExecutor :最常使用,推薦。 其實(shí)質(zhì)是對(duì)java.util.concurrent.ThreadPoolExecutor的包裝,

文章參考

相關(guān)文章

  • 關(guān)于feign.codec.DecodeException異常的解決方案

    關(guān)于feign.codec.DecodeException異常的解決方案

    這篇文章主要介紹了關(guān)于feign.codec.DecodeException異常的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 淺談Java 代理機(jī)制

    淺談Java 代理機(jī)制

    Java 有兩種代理方式,一種是靜態(tài)代理,另一種是動(dòng)態(tài)代理。如果我們?cè)诖a編譯時(shí)就確定了被代理的類是哪一個(gè),那么就可以直接使用靜態(tài)代理;如果不能確定,那么可以使用類的動(dòng)態(tài)加載機(jī)制,在代碼運(yùn)行期間加載被代理的類這就是動(dòng)態(tài)代理
    2021-06-06
  • Java超詳細(xì)講解設(shè)計(jì)模式中的命令模式

    Java超詳細(xì)講解設(shè)計(jì)模式中的命令模式

    命令模式是將一個(gè)請(qǐng)求封裝為一個(gè)對(duì)象,從而可用不同的請(qǐng)求對(duì)客戶進(jìn)行參數(shù)化,對(duì)請(qǐng)求排隊(duì)或者對(duì)請(qǐng)求做日志記錄,以及可以支持撤銷的操作
    2022-04-04
  • SpringBoot如何優(yōu)雅地使用Swagger2

    SpringBoot如何優(yōu)雅地使用Swagger2

    這篇文章主要介紹了SpringBoot如何優(yōu)雅地使用Swagger2,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • springboot使用redisTemplate操作lua腳本

    springboot使用redisTemplate操作lua腳本

    本文主要介紹了springboot使用redisTemplate操作lua腳本,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • JVM如何處理異常深入詳解

    JVM如何處理異常深入詳解

    異常處理的兩大元素:拋出異常、捕獲異常,非正常處理的兩個(gè)方法。下面這篇文章主要給大家介紹了關(guān)于JVM如何處理異常的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2019-01-01
  • 最新版Spring Security中的路徑匹配方案

    最新版Spring Security中的路徑匹配方案

    在 Spring Security 中,路徑匹配是權(quán)限控制的核心部分,它決定了哪些請(qǐng)求可以訪問(wèn)特定的資源,本文將詳細(xì)介紹 Spring Security 中的路徑匹配策略,并提供相應(yīng)的代碼示例,需要的朋友可以參考下
    2024-04-04
  • SPRING IOC注入方式過(guò)程解析

    SPRING IOC注入方式過(guò)程解析

    這篇文章主要介紹了SPRING IOC注入方式過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • Spring使用注解方式處理事務(wù)

    Spring使用注解方式處理事務(wù)

    這篇文章主要為大家詳細(xì)介紹了Spring使用注解方式處理事務(wù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-08-08
  • 使用Spring Security控制會(huì)話的方法

    使用Spring Security控制會(huì)話的方法

    在本文中,我們將說(shuō)明Spring Security如何允許我們控制HTTP會(huì)話。這篇文章主要介紹了使用Spring Security控制會(huì)話 ,需要的朋友可以參考下
    2019-05-05

最新評(píng)論

霍邱县| 交城县| 南木林县| 庄浪县| 马公市| 玉林市| 白山市| 牡丹江市| 应用必备| 桐梓县| 荣昌县| 安泽县| 沂源县| 微山县| 兴仁县| 鹤峰县| 略阳县| 海兴县| 集安市| 门源| 无极县| 榕江县| 阳江市| 德格县| 高陵县| 吉林省| 娄底市| 招远市| 盐源县| 平顺县| 南岸区| 通海县| 盐城市| 井研县| 观塘区| 东丽区| 信丰县| 彭山县| 霸州市| 呈贡县| 赞皇县|