激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - 編程技術 - 什么?用@Async會內存溢出?看看你的線程池配置了沒!

什么?用@Async會內存溢出?看看你的線程池配置了沒!

2021-09-18 01:23程序猿DD翟永超 編程技術

如果只是如前文那樣直接簡單的創建來使用,可能還是會碰到一些問題。存在有什么問題呢?先來思考下,下面的這個接口,通過異步任務加速執行的實現,是否存在問題或風險呢?

什么?用@Async會內存溢出?看看你的線程池配置了沒!

上一篇我們介紹了如何使用@Async注解來創建異步任務,我可以用這種方法來實現一些并發操作,以加速任務的執行效率。但是,如果只是如前文那樣直接簡單的創建來使用,可能還是會碰到一些問題。存在有什么問題呢?先來思考下,下面的這個接口,通過異步任務加速執行的實現,是否存在問題或風險呢?

  1. @RestController
  2. publicclassHelloController{
  3.  
  4. @Autowired
  5. privateAsyncTasksasyncTasks;
  6.  
  7. @GetMapping("/hello")
  8. publicStringhello(){
  9. //將可以并行的處理邏輯,拆分成三個異步任務同時執行
  10. CompletableFuturetask1=asyncTasks.doTaskOne();
  11. CompletableFuturetask2=asyncTasks.doTaskTwo();
  12. CompletableFuturetask3=asyncTasks.doTaskThree();
  13.  
  14. CompletableFuture.allOf(task1,task2,task3).join();
  15. return"HelloWorld";
  16. }
  17. }

雖然,從單次接口調用來說,是沒有問題的。但當接口被客戶端頻繁調用的時候,異步任務的數量就會大量增長:3 x n(n為請求數量),如果任務處理不夠快,就很可能會出現內存溢出的情況。那么為什么會內存溢出呢?根本原因是由于Spring Boot默認用于異步任務的線程池是這樣配置的:

什么?用@Async會內存溢出?看看你的線程池配置了沒!

圖中我標出的兩個重要參數是需要關注的:

  • queueCapacity:緩沖隊列的容量,默認為INT的最大值(2的31次方-1)。
  • maxSize:允許的最大線程數,默認為INT的最大值(2的31次方-1)。

所以,默認情況下,一般任務隊列就可能把內存給堆滿了。所以,我們真正使用的時候,還需要對異步任務的執行線程池做一些基礎配置,以防止出現內存溢出導致服務不可用的問題。

配置默認線程池

默認線程池的配置很簡單,只需要在配置文件中完成即可,主要有以下這些參數:

  1. spring.task.execution.pool.core-size=2
  2. spring.task.execution.pool.max-size=5
  3. spring.task.execution.pool.queue-capacity=10
  4. spring.task.execution.pool.keep-alive=60s
  5. spring.task.execution.pool.allow-core-thread-timeout=true
  6. spring.task.execution.shutdown.await-termination=false
  7. spring.task.execution.shutdown.await-termination-period=
  8. spring.task.execution.thread-name-prefix=task-

具體配置含義如下:

  • spring.task.execution.pool.core-size:線程池創建時的初始化線程數,默認為8
  • spring.task.execution.pool.max-size:線程池的最大線程數,默認為int最大值
  • spring.task.execution.pool.queue-capacity:用來緩沖執行任務的隊列,默認為int最大值
  • spring.task.execution.pool.keep-alive:線程終止前允許保持空閑的時間
  • spring.task.execution.pool.allow-core-thread-timeout:是否允許核心線程超時
  • spring.task.execution.shutdown.await-termination:是否等待剩余任務完成后才關閉應用
  • spring.task.execution.shutdown.await-termination-period:等待剩余任務完成的最大時間
  • spring.task.execution.thread-name-prefix:線程名的前綴,設置好了之后可以方便我們在日志中查看處理任務所在的線程池

動手試一試

我們直接基于之前chapter7-5的結果來進行如下操作。

首先,在沒有進行線程池配置之前,可以先執行一下單元測試:

  1. @Test
  2. publicvoidtest1()throwsException{
  3. longstart=System.currentTimeMillis();
  4.  
  5. CompletableFuturetask1=asyncTasks.doTaskOne();
  6. CompletableFuturetask2=asyncTasks.doTaskTwo();
  7. CompletableFuturetask3=asyncTasks.doTaskThree();
  8.  
  9. CompletableFuture.allOf(task1,task2,task3).join();
  10.  
  11. longend=System.currentTimeMillis();
  12.  
  13. log.info("任務全部完成,總耗時:"+(end-start)+"毫秒");
  14. }

由于默認線程池的核心線程數是8,所以3個任務會同時開始執行,日志輸出是這樣的:

  1. 2021-09-1500:30:14.819INFO77614---[task-2]com.didispace.chapter76.AsyncTasks:開始做任務二
  2. 2021-09-1500:30:14.819INFO77614---[task-3]com.didispace.chapter76.AsyncTasks:開始做任務三
  3. 2021-09-1500:30:14.819INFO77614---[task-1]com.didispace.chapter76.AsyncTasks:開始做任務一
  4. 2021-09-1500:30:15.491INFO77614---[task-2]com.didispace.chapter76.AsyncTasks:完成任務二,耗時:672毫秒
  5. 2021-09-1500:30:19.496INFO77614---[task-3]com.didispace.chapter76.AsyncTasks:完成任務三,耗時:4677毫秒
  6. 2021-09-1500:30:20.443INFO77614---[task-1]com.didispace.chapter76.AsyncTasks:完成任務一,耗時:5624毫秒
  7. 2021-09-1500:30:20.443INFO77614---[main]c.d.chapter76.Chapter76ApplicationTests:任務全部完成,總耗時:5653毫秒

接著,可以嘗試在配置文件中增加如下的線程池配置

  1. spring.task.execution.pool.core-size=2
  2. spring.task.execution.pool.max-size=5
  3. spring.task.execution.pool.queue-capacity=10
  4. spring.task.execution.pool.keep-alive=60s
  5. spring.task.execution.pool.allow-core-thread-timeout=true
  6. spring.task.execution.thread-name-prefix=task-

日志輸出的順序會變成如下的順序:

  1. 2021-09-1500:31:50.013INFO77985---[task-1]com.didispace.chapter76.AsyncTasks:開始做任務一
  2. 2021-09-1500:31:50.013INFO77985---[task-2]com.didispace.chapter76.AsyncTasks:開始做任務二
  3. 2021-09-1500:31:52.452INFO77985---[task-1]com.didispace.chapter76.AsyncTasks:完成任務一,耗時:2439毫秒
  4. 2021-09-1500:31:52.452INFO77985---[task-1]com.didispace.chapter76.AsyncTasks:開始做任務三
  5. 2021-09-1500:31:55.880INFO77985---[task-2]com.didispace.chapter76.AsyncTasks:完成任務二,耗時:5867毫秒
  6. 2021-09-1500:32:00.346INFO77985---[task-1]com.didispace.chapter76.AsyncTasks:完成任務三,耗時:7894毫秒
  7. 2021-09-1500:32:00.347INFO77985---[main]c.d.chapter76.Chapter76ApplicationTests:任務全部完成,總耗時:10363毫秒
  • 任務一和任務二會馬上占用核心線程,任務三進入隊列等待
  • 任務一完成,釋放出一個核心線程,任務三從隊列中移出,并占用核心線程開始處理

注意:這里可能有的小伙伴會問,最大線程不是5么,為什么任務三是進緩沖隊列,不是創建新線程來處理嗎?這里要理解緩沖隊列與最大線程間的關系:只有在緩沖隊列滿了之后才會申請超過核心線程數的線程來進行處理。所以,這里只有緩沖隊列中10個任務滿了,再來第11個任務的時候,才會在線程池中創建第三個線程來處理。這個這里就不具體寫列子了,讀者可以自己調整下參數,或者調整下單元測試來驗證這個邏輯。

原文鏈接:https://mp.weixin.qq.com/s/1LgXMWS26vJvfakrA24rNg

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 日韩精品一区二 | 嫩草99| 欧美日韩亚洲成人 | 亚洲精久久 | 精品一区二区在线视频 | 日本免费a∨| 欧美精品v国产精品v日韩精品 | 免费视频a | 国产一区国产二区在线观看 | 中文字幕一二区 | av成人在线观看 | 欧美人与性禽动交精品 | 久久久中精品2020中文 | 免费色片 | 国产精品啪一品二区三区粉嫩 | 亚洲影院久久久av天天蜜桃臀 | 国产91在线亚洲 | 国产成人精品免高潮在线观看 | 黄色网址在线播放 | 无码专区aaaaaa免费视频 | 国产品久久 | jizzyouxxxx| 在线天堂资源 | 日韩美香港a一级毛片免费 久久精品视频1 | 久久精品亚洲成在人线av网址 | 黄色欧美精品 | 毛片视频播放 | 日本一区二区免费在线观看 | 免费a级毛片永久免费 | 亚洲射情 | 国产91中文字幕 | 666sao| 黄色片免费在线 | 草莓福利社区在线 | 欧美一区二区黄 | 国产精品热 | 久久91精品国产91久久yfo | 91情侣在线偷精品国产 | 九九热在线视频观看 | 狠狠干天天操 | 亚洲午夜影院在线观看 |