国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > Java > 正文

Spring Boot利用@Async如何實現異步調用:自定義線程池

2024-07-14 08:40:33
字體:
來源:轉載
供稿:網友

前言

在之前的Spring Boot基礎教程系列中,已經通過《Spring Boot中使用@Async實現異步調用》一文介紹過如何使用@Async注解來實現異步調用了。但是,對于這些異步執行的控制是我們保障自身應用健康的基本技能。本文我們就來學習一下,如果通過自定義線程池的方式來控制異步調用的并發。

本文中的例子我們可以在之前的例子基礎上修改,也可以創建一個全新的Spring Boot項目來嘗試。

定義線程池

第一步,先在Spring Boot主類中定義一個線程池,比如:

@SpringBootApplicationpublic class Application { public static void main(String[] args) {  SpringApplication.run(Application.class, args); } @EnableAsync @Configuration class TaskPoolConfig {  @Bean("taskExecutor")  public Executor taskExecutor() {   ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();   executor.setCorePoolSize(10);   executor.setMaxPoolSize(20);   executor.setQueueCapacity(200);   executor.setKeepAliveSeconds(60);   executor.setThreadNamePrefix("taskExecutor-");   executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());   return executor;  } }}

上面我們通過使用ThreadPoolTaskExecutor創建了一個線程池,同時設置了以下這些參數:

  • 核心線程數10:線程池創建時候初始化的線程數
  • 最大線程數20:線程池最大的線程數,只有在緩沖隊列滿了之后才會申請超過核心線程數的線程
  • 緩沖隊列200:用來緩沖執行任務的隊列
  • 允許線程的空閑時間60秒:當超過了核心線程出之外的線程在空閑時間到達之后會被銷毀
  • 線程池名的前綴:設置好了之后可以方便我們定位處理任務所在的線程池
  • 線程池對拒絕任務的處理策略:這里采用了CallerRunsPolicy策略,當線程池沒有處理能力的時候,該策略會直接在 execute 方法的調用線程中運行被拒絕的任務;如果執行程序已關閉,則會丟棄該任務

使用線程池

在定義了線程池之后,我們如何讓異步調用的執行任務使用這個線程池中的資源來運行呢?方法非常簡單,我們只需要在@Async注解中指定線程池名即可,比如:

@Slf4j@Componentpublic class Task { public static Random random = new Random(); @Async("taskExecutor") public void doTaskOne() throws Exception {  log.info("開始做任務一");  long start = System.currentTimeMillis();  Thread.sleep(random.nextInt(10000));  long end = System.currentTimeMillis();  log.info("完成任務一,耗時:" + (end - start) + "毫秒"); } @Async("taskExecutor") public void doTaskTwo() throws Exception {  log.info("開始做任務二");  long start = System.currentTimeMillis();  Thread.sleep(random.nextInt(10000));  long end = System.currentTimeMillis();  log.info("完成任務二,耗時:" + (end - start) + "毫秒"); } @Async("taskExecutor") public void doTaskThree() throws Exception {  log.info("開始做任務三");  long start = System.currentTimeMillis();  Thread.sleep(random.nextInt(10000));  long end = System.currentTimeMillis();  log.info("完成任務三,耗時:" + (end - start) + "毫秒"); }}

單元測試

最后,我們來寫個單元測試來驗證一下

@RunWith(SpringJUnit4ClassRunner.class)@SpringBootTestpublic class ApplicationTests { @Autowired private Task task; @Test public void test() throws Exception {  task.doTaskOne();  task.doTaskTwo();  task.doTaskThree();  Thread.currentThread().join(); }}

執行上面的單元測試,我們可以在控制臺中看到所有輸出的線程名前都是之前我們定義的線程池前綴名開始的,說明我們使用線程池來執行異步任務的試驗成功了!

2018-03-27 22:01:15.620  INFO 73703 --- [ taskExecutor-1] com.didispace.async.Task                 : 開始做任務一
2018-03-27 22:01:15.620  INFO 73703 --- [ taskExecutor-2] com.didispace.async.Task                 : 開始做任務二
2018-03-27 22:01:15.620  INFO 73703 --- [ taskExecutor-3] com.didispace.async.Task                 : 開始做任務三
2018-03-27 22:01:18.165  INFO 73703 --- [ taskExecutor-2] com.didispace.async.Task                 : 完成任務二,耗時:2545毫秒
2018-03-27 22:01:22.149  INFO 73703 --- [ taskExecutor-3] com.didispace.async.Task                 : 完成任務三,耗時:6529毫秒
2018-03-27 22:01:23.912  INFO 73703 --- [ taskExecutor-1] com.didispace.async.Task                 : 完成任務一,耗時:8292毫秒

完整示例:

讀者可以根據喜好選擇下面查看Chapter4-1-3項目:

Github:https://github.com/dyc87112/SpringBoot-Learning/

Gitee:https://gitee.com/didispace/SpringBoot-Learning/

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 九龙坡区| 景德镇市| 永德县| 楚雄市| 炉霍县| 斗六市| 朝阳市| 彰化市| 张家港市| 临湘市| 青龙| 玉山县| 额尔古纳市| 渭源县| 旬邑县| 开原市| 东城区| 静乐县| 长治市| 南宫市| 平塘县| 滨海县| 同德县| 宁德市| 华池县| 桓台县| 元阳县| 五家渠市| 施秉县| 贺兰县| 天祝| 张北县| 武宁县| 正阳县| 钦州市| 宿州市| 庄浪县| 咸丰县| 乌拉特后旗| 金门县| 洞口县|