<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          SpringBoot線程池的創(chuàng)建、@Async配置步驟及注意事項(xiàng)

          共 6447字,需瀏覽 13分鐘

           ·

          2021-12-12 23:27

          點(diǎn)擊上方“程序員大白”,選擇“星標(biāo)”公眾號(hào)

          重磅干貨,第一時(shí)間送達(dá)

          前言

          最近在做訂單模塊,用戶購(gòu)買(mǎi)服務(wù)類(lèi)產(chǎn)品之后,需要進(jìn)行預(yù)約,預(yù)約成功之后分別給商家和用戶發(fā)送提醒短信??紤]發(fā)短信耗時(shí)的情況所以我想用異步的方法去執(zhí)行,于是就在網(wǎng)上看見(jiàn)了Spring的@Async了。

          但是遇到了許多問(wèn)題,使得@Async無(wú)效,也一直沒(méi)有找到很好的文章去詳細(xì)的說(shuō)明@Async的正確及錯(cuò)誤的使用方法及需要注意的地方,這里簡(jiǎn)單整理了一下遇見(jiàn)的問(wèn)題,Sring是以配置文件的形式來(lái)開(kāi)啟@Async,而SpringBoot則是以注解的方式開(kāi)啟。

          我們可以使用springBoot默認(rèn)的線程池,不過(guò)一般我們會(huì)自定義線程池(因?yàn)楸容^靈活),配置方式有:

          1. 使用 xml 文件配置的方式

          2. 使用Java代碼結(jié)合@Configuration進(jìn)行配置(推薦使用)

          下面分別實(shí)現(xiàn)兩種配置方式

          第一步、配置@Async

          一、springBoot啟動(dòng)類(lèi)的配置:

          在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同目錄下創(chuàng)建文件threadPool.xml文件:

          ??
          <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"?/>??

          第二步:創(chuàng)建兩個(gè)異步方法的類(lèi),如下所示:

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

          @Service??
          public?class?TranTest2Service?{??
          ??
          ??
          ????//?發(fā)送提醒短信?1??
          ????@Async??
          ????public?void?sendMessage1()?throws?InterruptedException?{??
          ??
          ????????System.out.println("發(fā)送短信方法----?1???執(zhí)行開(kāi)始");??
          ????????Thread.sleep(5000);?//?模擬耗時(shí)??
          ????????System.out.println("發(fā)送短信方法----?1???執(zhí)行結(jié)束");??
          ????}??
          ??
          ????//?發(fā)送提醒短信?2??
          ????@Async??
          ????public?void?sendMessage2()?throws?InterruptedException?{??
          ??
          ????????System.out.println("發(fā)送短信方法----?2???執(zhí)行開(kāi)始");??
          ????????Thread.sleep(2000);?//?模擬耗時(shí)??
          ????????System.out.println("發(fā)送短信方法----?2???執(zhí)行結(jié)束");??
          ????}??
          }??

          第二個(gè)類(lèi)。調(diào)用發(fā)短信的方法 (異步方法不能與被調(diào)用的異步方法在同一個(gè)類(lèi)中,否則無(wú)效):

          @Service??
          public?class?OrderTaskServic?{??
          ????@Autowired??
          ????private?TranTest2Service?tranTest2Service;??
          ??
          ????//?訂單處理任務(wù)??
          ????public?void?orderTask()?throws?InterruptedException?{??
          ??
          ????????this.cancelOrder();?//?取消訂單??
          ????????tranTest2Service.sendMessage1();?//?發(fā)短信的方法???1??
          ????????tranTest2Service.sendMessage2();?//?發(fā)短信的方法??2??
          ??
          ????}??
          ??
          ????//?取消訂單??
          ????public?void?cancelOrder()?throws?InterruptedException?{??
          ????????System.out.println("取消訂單的方法執(zhí)行------開(kāi)始");??
          ????????System.out.println("取消訂單的方法執(zhí)行------結(jié)束?");??
          ????}??
          ??
          }??

          經(jīng)過(guò)測(cè)試得到如下結(jié)果:

          1.沒(méi)有使用@Async

          2.使用了@Async

          可以看出,沒(méi)有使用@Async方式實(shí)現(xiàn)的發(fā)送短信是同步執(zhí)行的,意思就是說(shuō)第一條發(fā)送之后再發(fā)送第二條,第二條發(fā)送成功之后再給用戶提示,這樣顯然會(huì)影響用戶體驗(yàn),再看使用了@Async實(shí)現(xiàn)的,在執(zhí)行第一個(gè)發(fā)送短信方法之后馬上開(kāi)啟另一個(gè)線程執(zhí)行第二個(gè)方法,顯然這樣我們的處理速度回快很多。

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

          1. 新建一個(gè)配置類(lèi)

          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?{??
          ??
          /**???
          ?*???默認(rèn)情況下,在創(chuàng)建了線程池后,線程池中的線程數(shù)為0,當(dāng)有任務(wù)來(lái)之后,就會(huì)創(chuàng)建一個(gè)線程去執(zhí)行任務(wù),??
          ?*????當(dāng)線程池中的線程數(shù)目達(dá)到corePoolSize后,就會(huì)把到達(dá)的任務(wù)放到緩存隊(duì)列當(dāng)中;??
          ?*??當(dāng)隊(duì)列滿了,就繼續(xù)創(chuàng)建線程,當(dāng)線程數(shù)量大于等于maxPoolSize后,開(kāi)始使用拒絕策略拒絕???
          ?*/
          ??
          ??
          ????/**?核心線程數(shù)(默認(rèn)線程數(shù))?*/??
          ????private?static?final?int?corePoolSize?=?20;??
          ????/**?最大線程數(shù)?*/??
          ????private?static?final?int?maxPoolSize?=?100;??
          ????/**?允許線程空閑時(shí)間(單位:默認(rèn)為秒)?*/??
          ????private?static?final?int?keepAliveTime?=?10;??
          ????/**?緩沖隊(duì)列大小?*/??
          ????private?static?final?int?queueCapacity?=?200;??
          ????/**?線程池名前綴?*/??
          ????private?static?final?String?threadNamePrefix?=?"Async-Service-";??
          ??
          ????@Bean("taskExecutor")?//?bean的名稱(chēng),默認(rèn)為首字母小寫(xiě)的方法名??
          ????public?ThreadPoolTaskExecutor?taskExecutor(){??
          ????????ThreadPoolTaskExecutor?executor?=?new?ThreadPoolTaskExecutor();??
          ????????executor.setCorePoolSize(corePoolSize);?????
          ????????executor.setMaxPoolSize(maxPoolSize);??
          ????????executor.setQueueCapacity(queueCapacity);??
          ????????executor.setKeepAliveSeconds(keepAliveTime);??
          ????????executor.setThreadNamePrefix(threadNamePrefix);??
          ??
          ????????//?線程池對(duì)拒絕任務(wù)的處理策略??
          ????????// CallerRunsPolicy:由調(diào)用線程(提交任務(wù)的線程)處理該任務(wù)??
          ????????executor.setRejectedExecutionHandler(new?ThreadPoolExecutor.CallerRunsPolicy());??
          ????????//?初始化??
          ????????executor.initialize();??
          ????????return?executor;??
          ????}??
          }??

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

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

          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);??
          ??
          ????//?發(fā)送提醒短信?1??
          ????????@PostConstruct?//?加上該注解項(xiàng)目啟動(dòng)時(shí)就執(zhí)行一次該方法??
          ????@Async("taskExecutor")??
          ????public?void?sendMessage1()?throws?InterruptedException?{??
          ????????log.info("發(fā)送短信方法----?1???執(zhí)行開(kāi)始");??
          ????????Thread.sleep(5000);?//?模擬耗時(shí)??
          ????????log.info("發(fā)送短信方法----?1???執(zhí)行結(jié)束");??
          ????}??
          ??
          ????//?發(fā)送提醒短信?2??
          ????????@PostConstruct?//?加上該注解項(xiàng)目啟動(dòng)時(shí)就執(zhí)行一次該方法??
          ????@Async("taskExecutor")??
          ????public?void?sendMessage2()?throws?InterruptedException?{??
          ??
          ????????log.info("發(fā)送短信方法----?2???執(zhí)行開(kāi)始");??
          ????????Thread.sleep(2000);?//?模擬耗時(shí)??
          ????????log.info("發(fā)送短信方法----?2???執(zhí)行結(jié)束");??
          ????}??
          }??

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

          第二個(gè)類(lèi)。調(diào)用發(fā)短信的方法 (異步方法不能與被調(diào)用的異步方法在同一個(gè)類(lèi)中,否則無(wú)效):

          @Service??
          public?class?OrderTaskServic?{??
          ????@Autowired??
          ????private?TranTest2Service?tranTest2Service;??
          ??
          ????//?訂單處理任務(wù)??
          ????public?void?orderTask()?throws?InterruptedException?{??
          ??
          ????????this.cancelOrder();?//?取消訂單??
          ????????tranTest2Service.sendMessage1();?//?發(fā)短信的方法???1??
          ????????tranTest2Service.sendMessage2();?//?發(fā)短信的方法??2??
          ??
          ????}??
          ??
          ????//?取消訂單??
          ????public?void?cancelOrder()?throws?InterruptedException?{??
          ????????System.out.println("取消訂單的方法執(zhí)行------開(kāi)始");??
          ????????System.out.println("取消訂單的方法執(zhí)行------結(jié)束?");??
          ????}??
          ??
          }??

          運(yùn)行截圖:

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

          [Async-Service-1]、[Async-Service-2]表示線程1和線程2 ,是我們自定義的線程池里面的線程名稱(chēng),我們?cè)谂渲妙?lèi)里面定義的線程池前綴:

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

          注意事項(xiàng)

          如下方式會(huì)使@Async失效

          • 異步方法使用static修飾

          • 異步類(lèi)沒(méi)有使用@Component注解(或其他注解)導(dǎo)致spring無(wú)法掃描到異步類(lèi)

          • 異步方法不能與被調(diào)用的異步方法在同一個(gè)類(lèi)中

          • 類(lèi)中需要使用@Autowired或@Resource等注解自動(dòng)注入,不能自己手動(dòng)new對(duì)象

          • 如果使用SpringBoot框架必須在啟動(dòng)類(lèi)中增加@EnableAsync注解

          來(lái)源:blog.csdn.net/Muscleheng/article/details/81409672


          13個(gè)你一定要知道的PyTorch特性

          解讀:為什么要做特征歸一化/標(biāo)準(zhǔn)化?

          一文搞懂 PyTorch 內(nèi)部機(jī)制

          張一鳴:每個(gè)逆襲的年輕人,都具備的底層能力


          關(guān)


          ,學(xué),西學(xué)學(xué)運(yùn)營(yíng)護(hù)號(hào)樂(lè)質(zhì),結(jié)識(shí),關(guān)[],學(xué)習(xí)進(jìn)!


          瀏覽 37
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  偷拍日本大香蕉 | 91日韩在线视频 | 久久婷婷综合网 | 老司机福利院 | www.69自拍 |