成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

什么?用@Async會(huì)內(nèi)存溢出?看看你的線程池配置了沒!

存儲(chǔ)
如果只是如前文那樣直接簡(jiǎn)單的創(chuàng)建來使用,可能還是會(huì)碰到一些問題。存在有什么問題呢?先來思考下,下面的這個(gè)接口,通過異步任務(wù)加速執(zhí)行的實(shí)現(xiàn),是否存在問題或風(fēng)險(xiǎn)呢?

[[424482]]

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

  1. @RestController 
  2. public class HelloController { 
  3.  
  4.     @Autowired 
  5.     private AsyncTasks asyncTasks; 
  6.          
  7.     @GetMapping("/hello"
  8.     public String hello() { 
  9.         // 將可以并行的處理邏輯,拆分成三個(gè)異步任務(wù)同時(shí)執(zhí)行 
  10.         CompletableFuture<String> task1 = asyncTasks.doTaskOne(); 
  11.         CompletableFuture<String> task2 = asyncTasks.doTaskTwo(); 
  12.         CompletableFuture<String> task3 = asyncTasks.doTaskThree(); 
  13.          
  14.         CompletableFuture.allOf(task1, task2, task3).join(); 
  15.         return "Hello World"
  16.     } 

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

圖中我標(biāo)出的兩個(gè)重要參數(shù)是需要關(guān)注的:

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

所以,默認(rèn)情況下,一般任務(wù)隊(duì)列就可能把內(nèi)存給堆滿了。所以,我們真正使用的時(shí)候,還需要對(duì)異步任務(wù)的執(zhí)行線程池做一些基礎(chǔ)配置,以防止出現(xiàn)內(nèi)存溢出導(dǎo)致服務(wù)不可用的問題。

配置默認(rèn)線程池

默認(rèn)線程池的配置很簡(jiǎn)單,只需要在配置文件中完成即可,主要有以下這些參數(shù):

  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:線程池創(chuàng)建時(shí)的初始化線程數(shù),默認(rèn)為8
  • spring.task.execution.pool.max-size:線程池的最大線程數(shù),默認(rèn)為int最大值
  • spring.task.execution.pool.queue-capacity:用來緩沖執(zhí)行任務(wù)的隊(duì)列,默認(rèn)為int最大值
  • spring.task.execution.pool.keep-alive:線程終止前允許保持空閑的時(shí)間
  • spring.task.execution.pool.allow-core-thread-timeout:是否允許核心線程超時(shí)
  • spring.task.execution.shutdown.await-termination:是否等待剩余任務(wù)完成后才關(guān)閉應(yīng)用
  • spring.task.execution.shutdown.await-termination-period:等待剩余任務(wù)完成的最大時(shí)間
  • spring.task.execution.thread-name-prefix:線程名的前綴,設(shè)置好了之后可以方便我們?cè)谌罩局胁榭刺幚砣蝿?wù)所在的線程池

動(dòng)手試一試

我們直接基于之前chapter7-5的結(jié)果來進(jìn)行如下操作。

首先,在沒有進(jìn)行線程池配置之前,可以先執(zhí)行一下單元測(cè)試:

  1. @Test 
  2. public void test1() throws Exception { 
  3.     long start = System.currentTimeMillis(); 
  4.  
  5.     CompletableFuture<String> task1 = asyncTasks.doTaskOne(); 
  6.     CompletableFuture<String> task2 = asyncTasks.doTaskTwo(); 
  7.     CompletableFuture<String> task3 = asyncTasks.doTaskThree(); 
  8.  
  9.     CompletableFuture.allOf(task1, task2, task3).join(); 
  10.  
  11.     long end = System.currentTimeMillis(); 
  12.  
  13.     log.info("任務(wù)全部完成,總耗時(shí):" + (end - start) + "毫秒"); 

由于默認(rèn)線程池的核心線程數(shù)是8,所以3個(gè)任務(wù)會(huì)同時(shí)開始執(zhí)行,日志輸出是這樣的:

  1. 2021-09-15 00:30:14.819  INFO 77614 --- [         task-2] com.didispace.chapter76.AsyncTasks       : 開始做任務(wù)二 
  2. 2021-09-15 00:30:14.819  INFO 77614 --- [         task-3] com.didispace.chapter76.AsyncTasks       : 開始做任務(wù)三 
  3. 2021-09-15 00:30:14.819  INFO 77614 --- [         task-1] com.didispace.chapter76.AsyncTasks       : 開始做任務(wù)一 
  4. 2021-09-15 00:30:15.491  INFO 77614 --- [         task-2] com.didispace.chapter76.AsyncTasks       : 完成任務(wù)二,耗時(shí):672毫秒 
  5. 2021-09-15 00:30:19.496  INFO 77614 --- [         task-3] com.didispace.chapter76.AsyncTasks       : 完成任務(wù)三,耗時(shí):4677毫秒 
  6. 2021-09-15 00:30:20.443  INFO 77614 --- [         task-1] com.didispace.chapter76.AsyncTasks       : 完成任務(wù)一,耗時(shí):5624毫秒 
  7. 2021-09-15 00:30:20.443  INFO 77614 --- [           main] c.d.chapter76.Chapter76ApplicationTests  : 任務(wù)全部完成,總耗時(shí):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- 

日志輸出的順序會(huì)變成如下的順序:

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

 

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

 

責(zé)任編輯:武曉燕 來源: 程序猿DD
相關(guān)推薦

2021-09-08 08:40:59

藍(lán)牙芯片漏洞

2013-07-31 10:41:58

2018-10-29 10:35:48

2017-05-23 11:57:58

2018-10-23 17:08:11

CIOIT人才

2021-06-02 07:57:48

內(nèi)存管理

2018-08-24 20:57:55

程序員編程語言Python

2024-09-09 09:41:03

內(nèi)存溢出golang開發(fā)者

2014-08-21 12:07:43

2020-03-05 09:51:20

內(nèi)存分頁映射

2021-09-14 13:21:22

安全數(shù)據(jù)庫(kù)安全工具

2013-10-22 10:40:26

2021-01-28 13:42:37

線程池業(yè)務(wù)場(chǎng)景

2019-01-18 16:39:08

系統(tǒng)層中間件層應(yīng)用層

2024-07-15 08:20:24

2024-03-05 08:33:52

OptionsAPIcomuted

2024-06-13 00:54:19

2025-01-09 11:24:59

線程池美團(tuán)動(dòng)態(tài)配置中心

2019-11-07 13:22:15

戴爾

2009-10-14 08:41:41

Windows 7XP模式支持CPU
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩视频一区二区三区 | 一区二区三区在线 | 精品麻豆剧传媒av国产九九九 | 国产日韩精品一区 | 91精品国产色综合久久不卡98口 | 日韩欧美一区二区三区免费观看 | 亚洲视频一区 | 中文字幕亚洲区一区二 | 久久久精品网站 | 国产精品久久 | 成人免费视频网站在线看 | 久久久久久国产精品免费免费 | 亚洲欧美在线观看视频 | 18成人在线观看 | 亚洲欧美日韩网站 | 欧美性受xxxx | 天堂视频中文在线 | 久久综合久久自在自线精品自 | 求毛片| 色综合久久久久 | 国产真实精品久久二三区 | 国产九九九九 | 日韩在线欧美 | 国产午夜精品一区二区三区 | 久久成人av | 免费欧美视频 | 在线观看国产三级 | 亚洲日本中文 | а√中文在线8 | 欧美日韩综合视频 | 91精品国产91久久久久久吃药 | 日本黄色激情视频 | 亚洲国产精品99久久久久久久久 | 国产高清在线精品 | 久久久精品一区二区三区 | 亚洲欧美日韩中文字幕一区二区三区 | 做a视频在线观看 | 国产免费一区二区 | 中文字幕av一区二区三区 | 91电影院| 亚洲免费观看视频 |