日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
詳解SpringBoot中的異步調(diào)用@Async

如何開(kāi)啟異步調(diào)用

在SpringBoot中,只需要給方法加上@Async注解,就能將同步方法變?yōu)楫惒秸{(diào)用。

首先在啟動(dòng)類上添加@EnableAsync,即開(kāi)啟異步調(diào)用。

 
 
 
 
  1. /**
  2.  * @author qcy
  3.  */
  4. @SpringBootApplication
  5. @EnableAsync
  6. public class AsyncApplication {
  7.     public static void main(String[] args) {
  8.         SpringApplication.run(AsyncApplication.class, args);
  9.     }
  10. }

在需要異步調(diào)用的方法上加上@Async注解

 
 
 
 
  1. package com.yang.async;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.scheduling.annotation.Async;
  4. import org.springframework.scheduling.annotation.AsyncResult;
  5. import org.springframework.stereotype.Component;
  6. import java.util.concurrent.Future;
  7. import java.util.concurrent.FutureTask;
  8. /**
  9.  * @author qcy
  10.  * @create 2020/09/09 14:01:35
  11.  */
  12. @Slf4j
  13. @Component
  14. public class Task {
  15.     @Async
  16.     public void method1() {
  17.         log.info("method1開(kāi)始,執(zhí)行線程為" + Thread.currentThread().getName());
  18.         try {
  19.             Thread.sleep(2000);
  20.         } catch (InterruptedException e) {
  21.             e.printStackTrace();
  22.         }
  23.         log.info("method1結(jié)束");
  24.     }
  25.     @Async
  26.     public void method2() {
  27.         log.info("method2開(kāi)始,執(zhí)行線程為" + Thread.currentThread().getName());
  28.         try {
  29.             Thread.sleep(3000);
  30.         } catch (InterruptedException e) {
  31.             e.printStackTrace();
  32.         }
  33.         log.info("method2結(jié)束");
  34.     }
  35. }

 測(cè)試一下:

 
 
 
 
  1. @SpringBootTest
  2. @Slf4j
  3. public class AsyncApplicationTests {
  4.     @Autowired
  5.     Task task;
  6.     @Test
  7.     public void testAsyncWithVoidReturn() throws InterruptedException {
  8.         log.info("main線程開(kāi)始");
  9.         task.method1();
  10.         task.method2();
  11.         //確保兩個(gè)異步調(diào)用執(zhí)行完成
  12.         Thread.sleep(6000);
  13.         log.info("main線程結(jié)束");
  14.     }
  15. }

 輸出如下:

可以看得出,SpringBoot創(chuàng)建了一個(gè)名為applicationTaskExecutor的線程池,使用這里面的線程來(lái)執(zhí)行異步調(diào)用。

這里值得注意的是,不要在一個(gè)類中調(diào)用@Async標(biāo)注的方法,否則不會(huì)起到異步調(diào)用的作用,至于為什么會(huì)產(chǎn)生這樣的問(wèn)題,需要深入到源碼中一探究竟,會(huì)另開(kāi)篇幅。

既然默認(rèn)使用的是SpringBoot自己創(chuàng)建的applicationTaskExecutor,那如何自己去定義一個(gè)線程池呢?

自定義線程池

我們需要手動(dòng)創(chuàng)建一個(gè)名為asynTaskExecutord的Bean

 
 
 
 
  1. package com.yang.async;
  2. import lombok.extern.slf4j.Slf4j;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.core.task.AsyncTaskExecutor;
  6. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  7. import java.util.concurrent.ThreadPoolExecutor;
  8. /**
  9.  * @author qcy
  10.  * @create 2020/09/09 15:31:07
  11.  */
  12. @Slf4j
  13. @Configuration
  14. public class AsyncConfig {
  15.     @Bean
  16.     public AsyncTaskExecutor asyncTaskExecutor() {
  17.         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  18.         executor.setCorePoolSize(8);
  19.         executor.setMaxPoolSize(16);
  20.         executor.setQueueCapacity(50);
  21.         executor.setAllowCoreThreadTimeOut(true);
  22.         executor.setKeepAliveSeconds(10);
  23.         executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
  24.         executor.setThreadNamePrefix("async-thread-pool-thread");
  25.         return executor;
  26.     }
  27. }

 對(duì)以上參數(shù)不了解的同學(xué),可以參考我的這篇文章說(shuō)說(shuō)線程池

其他類不需要變動(dòng),直接運(yùn)行剛才的testAsyncWithVoidReturn()方法,輸出:

看得出來(lái),現(xiàn)在是我們自定義的線程池

如果關(guān)心異步調(diào)用的返回值,又怎么處理?

獲取異步調(diào)用的返回結(jié)果

獲取異步調(diào)用的結(jié)果,需要利用Future機(jī)制,可以參考我的另外一篇文章談?wù)凴unnable、Future、Callable、FutureTask之間的關(guān)系

為T(mén)ask類增加以下兩個(gè)方法:

 
 
 
 
  1. @Async
  2.   public Future method3() {
  3.       log.info("method3開(kāi)始,執(zhí)行線程為" + Thread.currentThread().getName());
  4.       try {
  5.           Thread.sleep(1000);
  6.       } catch (InterruptedException e) {
  7.           e.printStackTrace();
  8.       }
  9.       log.info("method3結(jié)束");
  10.       return new AsyncResult<>("method3");
  11.   }
  12.   @Async
  13.   public Future method4() {
  14.       log.info("method4開(kāi)始,執(zhí)行線程為" + Thread.currentThread().getName());
  15.       try {
  16.           Thread.sleep(3000);
  17.       } catch (InterruptedException e) {
  18.           e.printStackTrace();
  19.       }
  20.       log.info("method4結(jié)束");
  21.       return new AsyncResult<>("method4");
  22.   }

 測(cè)試類:

 
 
 
 
  1. @Test
  2.   public void testAsyncWithStringReturn() throws InterruptedException, ExecutionException {
  3.       log.info("main線程開(kāi)始");
  4.       Future method3Result = task.method3();
  5.       Future method4Result = task.method4();
  6.       //get方法為阻塞獲取
  7.       log.info("method3執(zhí)行的返回結(jié)果:{}", method3Result.get());
  8.       log.info("method4執(zhí)行的返回結(jié)果:{}", method4Result.get());
  9.       log.info("main線程結(jié)束");
  10.   }

 輸出:

如圖,在主線程結(jié)束前,獲取到了異步調(diào)用的結(jié)果。且在兩個(gè)異步調(diào)用都結(jié)束的情況下,繼續(xù)執(zhí)行主線程。


文章名稱:詳解SpringBoot中的異步調(diào)用@Async
網(wǎng)頁(yè)網(wǎng)址:http://m.5511xx.com/article/dpddhdo.html