日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

@async 默认线程池_SpringBoot 线程池的使用

發布時間:2025/3/8 javascript 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 @async 默认线程池_SpringBoot 线程池的使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
??Java大聯盟

? 幫助萬千Java學習者持續成長

關注

作者|Muscleheng

blog.csdn.net/Muscleheng/article/details/81409672

前言

最近在做訂單模塊,用戶購買服務類產品之后,需要進行預約,預約成功之后分別給商家和用戶發送提醒短信。考慮發短信耗時的情況所以我想用異步的方法去執行,于是就在網上看見了Spring的@Async了。

但是遇到了許多問題,使得@Async無效,也一直沒有找到很好的文章去詳細的說明@Async的正確及錯誤的使用方法及需要注意的地方,這里簡單整理了一下遇見的問題,Sring是以配置文件的形式來開啟@Async,而SpringBoot則是以注解的方式開啟。

我們可以使用springBoot默認的線程池,不過一般我們會自定義線程池(因為比較靈活),配置方式有:

  • 使用 xml 文件配置的方式

  • 使用Java代碼結合@Configuration進行配置(推薦使用)

  • 下面分別實現兩種配置方式

    第一步、配置@Async

    一、springBoot啟動類的配置:

    在Spring Boot的主程序中配置@EnableAsync,如下所示:

    @ServletComponentScan
    @SpringBootApplication
    @EnableAsync
    public?class?ClubApiApplication?{
    ????public?static?void?main(String[]?args)?{
    ????????SpringApplication.run(ClubApiApplication.class,?args);
    ????}
    }

    二、Spring XML的配置方式:

    1.applicationContext.xml同目錄下創建文件threadPool.xml文件:

    <?xml ?version="1.0"?encoding="UTF-8"?>
    <beans?xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:task="http://www.springframework.org/schema/task"xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans.xsd
    ????????????????????????http://www.springframework.org/schema/task?http://www.springframework.org/schema/task/spring-task.xsd">

    ????
    ????<task:annotation-driven?executor="threadPool"?/>

    ????
    ????<bean?id="threadPool"class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
    ????????
    ????????<property?name="corePoolSize"?value="10"?/>

    ????????
    ????????<property?name="maxPoolSize"?value="50"?/>

    ????????
    ????????<property?name="queueCapacity"?value="100"?/>

    ????????
    ????????<property?name="keepAliveSeconds"?value="30"?/>

    ????????
    ????????<property?name="waitForTasksToCompleteOnShutdown"?value="true"?/>

    ????????
    ????????<property?name="allowCoreThreadTimeOut"?value="true"?/>

    ????????
    ????????<property?name="rejectedExecutionHandler">
    ????????????
    ????????????
    ????????????
    ????????????
    ????????????<bean?class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"?/>
    ????????property>
    ????bean>
    beans>

    2.然后在applicationContext.xml中引入threadPool.xml:



    <import?resource="threadPool.xml"?/>
    <task:annotation-driven?executor="WhifExecutor"?/>

    第二步:創建兩個異步方法的類,如下所示:

    第一個類(這里模擬取消訂單后發短信,有兩個發送短信的方法):

    @Service
    public?class?TranTest2Service?{


    ????//?發送提醒短信?1
    ????@Async
    ????public?void?sendMessage1()?throws?InterruptedException?{

    ????????System.out.println("發送短信方法----?1???執行開始");
    ????????Thread.sleep(5000);?//?模擬耗時
    ????????System.out.println("發送短信方法----?1???執行結束");
    ????}

    ????//?發送提醒短信?2
    ????@Async
    ????public?void?sendMessage2()?throws?InterruptedException?{

    ????????System.out.println("發送短信方法----?2???執行開始");
    ????????Thread.sleep(2000);?//?模擬耗時
    ????????System.out.println("發送短信方法----?2???執行結束");
    ????}
    }

    第二個類。調用發短信的方法 (異步方法不能與被調用的異步方法在同一個類中,否則無效):

    @Service
    public?class?OrderTaskServic?{
    ????@Autowired
    ????private?TranTest2Service?tranTest2Service;

    ????//?訂單處理任務
    ????public?void?orderTask()?throws?InterruptedException?{

    ????????this.cancelOrder();?//?取消訂單
    ????????tranTest2Service.sendMessage1();?//?發短信的方法???1
    ????????tranTest2Service.sendMessage2();?//?發短信的方法??2

    ????}

    ????//?取消訂單
    ????public?void?cancelOrder()?throws?InterruptedException?{
    ????????System.out.println("取消訂單的方法執行------開始");
    ????????System.out.println("取消訂單的方法執行------結束?");
    ????}

    }

    經過測試得到如下結果:

    1.沒有使用@Async

    2.使用了@Async

    可以看出,沒有使用@Async方式實現的發送短信是同步執行的,意思就是說第一條發送之后再發送第二條,第二條發送成功之后再給用戶提示,這樣顯然會影響用戶體驗,再看使用了@Async實現的,在執行第一個發送短信方法之后馬上開啟另一個線程執行第二個方法,顯然這樣我們的處理速度回快很多。

    使用Java代碼結合@Configuration注解的配置方式(推薦使用)

    1. 新建一個配置類

    package?com.boot.common.conf;

    import?java.util.concurrent.ThreadPoolExecutor;

    import?org.springframework.context.annotation.Bean;
    import?org.springframework.context.annotation.Configuration;
    import?org.springframework.scheduling.annotation.EnableAsync;
    import?org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

    /**
    ?*?線程池配置
    ?*?@author?zhh
    ?*
    ?*/
    @Configuration
    @EnableAsync
    public?class?ThreadPoolTaskConfig?{

    /**?
    ?*???默認情況下,在創建了線程池后,線程池中的線程數為0,當有任務來之后,就會創建一個線程去執行任務,
    ?*????當線程池中的線程數目達到corePoolSize后,就會把到達的任務放到緩存隊列當中;
    ?*??當隊列滿了,就繼續創建線程,當線程數量大于等于maxPoolSize后,開始使用拒絕策略拒絕?
    ?*/

    ????/**?核心線程數(默認線程數)?*/
    ????private?static?final?int?corePoolSize?=?20;
    ????/**?最大線程數?*/
    ????private?static?final?int?maxPoolSize?=?100;
    ????/**?允許線程空閑時間(單位:默認為秒)?*/
    ????private?static?final?int?keepAliveTime?=?10;
    ????/**?緩沖隊列大小?*/
    ????private?static?final?int?queueCapacity?=?200;
    ????/**?線程池名前綴?*/
    ????private?static?final?String?threadNamePrefix?=?"Async-Service-";

    ????@Bean("taskExecutor")?//?bean的名稱,默認為首字母小寫的方法名
    ????public?ThreadPoolTaskExecutor?taskExecutor(){
    ????????ThreadPoolTaskExecutor?executor?=?new?ThreadPoolTaskExecutor();
    ????????executor.setCorePoolSize(corePoolSize);???
    ????????executor.setMaxPoolSize(maxPoolSize);
    ????????executor.setQueueCapacity(queueCapacity);
    ????????executor.setKeepAliveSeconds(keepAliveTime);
    ????????executor.setThreadNamePrefix(threadNamePrefix);

    ????????//?線程池對拒絕任務的處理策略
    ????????// CallerRunsPolicy:由調用線程(提交任務的線程)處理該任務
    ????????executor.setRejectedExecutionHandler(new?ThreadPoolExecutor.CallerRunsPolicy());
    ????????//?初始化
    ????????executor.initialize();
    ????????return?executor;
    ????}
    }

    2.創建兩個異步方法的類(和之前的類類似僅僅是方法上注解不一樣),如下所示:

    第一個類(這里模擬取消訂單后發短信,有兩個發送短信的方法):

    package?com.boot.test1.service;

    import?org.slf4j.Logger;
    import?org.slf4j.LoggerFactory;
    import?org.springframework.scheduling.annotation.Async;
    import?org.springframework.stereotype.Service;

    @Service
    public?class?TranTest2Service?{
    ????Logger?log?=?LoggerFactory.getLogger(TranTest2Service.class);

    ????//?發送提醒短信?1
    ????????@PostConstruct?//?加上該注解項目啟動時就執行一次該方法
    ????@Async("taskExecutor")
    ????public?void?sendMessage1()?throws?InterruptedException?{
    ????????log.info("發送短信方法----?1???執行開始");
    ????????Thread.sleep(5000);?//?模擬耗時
    ????????log.info("發送短信方法----?1???執行結束");
    ????}

    ????//?發送提醒短信?2
    ????????@PostConstruct?//?加上該注解項目啟動時就執行一次該方法
    ????@Async("taskExecutor")
    ????public?void?sendMessage2()?throws?InterruptedException?{

    ????????log.info("發送短信方法----?2???執行開始");
    ????????Thread.sleep(2000);?//?模擬耗時
    ????????log.info("發送短信方法----?2???執行結束");
    ????}
    }

    代碼中的 @Async("taskExecutor") 對應我們自定義線程池中的 @Bean("taskExecutor") ,表示使用我們自定義的線程池。

    第二個類。調用發短信的方法 (異步方法不能與被調用的異步方法在同一個類中,否則無效):

    @Service
    public?class?OrderTaskServic?{
    ????@Autowired
    ????private?TranTest2Service?tranTest2Service;

    ????//?訂單處理任務
    ????public?void?orderTask()?throws?InterruptedException?{

    ????????this.cancelOrder();?//?取消訂單
    ????????tranTest2Service.sendMessage1();?//?發短信的方法???1
    ????????tranTest2Service.sendMessage2();?//?發短信的方法??2

    ????}

    ????//?取消訂單
    ????public?void?cancelOrder()?throws?InterruptedException?{
    ????????System.out.println("取消訂單的方法執行------開始");
    ????????System.out.println("取消訂單的方法執行------結束?");
    ????}

    }

    運行截圖:

    注意看,截圖中的 [nio-8090-exec-1] 是Tomcat的線程名稱

    [Async-Service-1]、[Async-Service-2]表示線程1和線程2 ,是我們自定義的線程池里面的線程名稱,我們在配置類里面定義的線程池前綴:

    private static final String threadNamePrefix = "Async-Service-"; // 線程池名前綴,說明我們自定義的線程池被使用了。

    注意事項

    如下方式會使@Async失效

    • 異步方法使用static修飾

    • 異步類沒有使用@Component注解(或其他注解)導致spring無法掃描到異步類

    • 異步方法不能與被調用的異步方法在同一個類中

    • 類中需要使用@Autowired或@Resource等注解自動注入,不能自己手動new對象

    • 如果使用SpringBoot框架必須在啟動類中增加@EnableAsync注解

    推薦閱讀

    1、B站原創,2020版前后端分離視頻教程

    2、Spring Boot源碼解析

    3、一文搞懂前后端分離

    4、快速上手Spring Boot+Vue前后端分離

    楠哥簡介

    資深 Java 工程師,微信號?nnsouthwind

    《Java零基礎實戰》一書作者,今日頭條認證大V

    GitChat認證作者,B站認證UP主(楠哥教你學Java)

    致力于幫助萬千 Java 學習者持續成長。

    有收獲,就在看

    總結

    以上是生活随笔為你收集整理的@async 默认线程池_SpringBoot 线程池的使用的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。