互聯網大廠Java面試題:使用無界隊列的線程池會致使內存飆升嗎?【石杉的架構筆記】

歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)程序員

週一至週五早8點半!精品技術文章準時送上!面試

精品學習資料獲取通道,參見文末

目錄

(1)背景引入算法

(2)線程池是如何構造的?緩存

(3)線程池的運行原理性能優化

(4)無界隊列引起的內存飆升架構

(1)背景引入

今天跟你們聊一個互聯網大廠的Java面試題:使用無界隊列的線程池會致使內存飆升嗎?併發

由於在面互聯網大廠的時候,必定會問併發,問併發的時候必定會問到線程池,問到線程池必定會問構造線程池的一些參數的含義。分佈式

而後,有一些面試官會就線程池的具體場景,問一些可能會遇到的問題。微服務

因此,在這裏就可能有上述那樣一個面試中的問題,算是Java面試裏相對來講高階一點的。高併發

我相信你們必定起碼知道線程池是個什麼東西的。簡單來講,就是維護一個池子,池子裏面放了不少的線程。

而後來一個任務,某個線程就獲取這個任務來執行,任務執行完以後線程是不會釋放掉的,而是停留在線程池裏繼續等待下一個任務。

這樣的一個好處是你不必本身手動頻繁的建立和銷燬線程,畢竟線程是較重的資源,頻繁的建立和銷燬對系統性能是沒好處的。

咱們看看下面的圖,回顧一下線程池的含義。

(2)線程池是如何構造的?

那麼平時在Java裏寫代碼的時候,你們記得不記得線程池是如何構造出來的呢?

是否是相似下面那樣的代碼,好比說咱們構造一個線程數量固定的一個線程池:

那麼Executors.newFixedThreadPool(10)內部到底又是如何構造出來線程池的呢?

其實很簡單,翻開JDK源碼就能夠看到裏面的代碼以下:

簡單來講,就是構造了一個ThreadPoolExecutor對象實例,你大體就認爲他是一個線程池吧,傳入了一些參數,這些參數大體包含了:

corePoolSize maximumPoolSize keepAliveTime workQueue

假如說咱們構造線程池傳入的線程數量是10,那麼在這裏,corePoolSize和maximumSize都是10,keepAliveTime默認就是0,workQueue是一個無界的LinkedBlockingQueue。

接下來,咱們具體來看看構造一個線程池傳入一些參數以後,具體這個線程池的運行原理是什麼。

(3)線程池的運行原理

簡單來講,剛開始的時候其實線程池裏是空的,就是一個線程都沒有的,以下圖所示。

接着若是你使用線程池提交一個任務進去,但願由線程池裏的一個線程來執行,以下代碼所示,就是提交一個任務:

這個時候,線程池會先看一下,如今池子裏的線程數量有沒有有達到corePoolSize指定的數量。

如今線程池裏的線程數量是0,而後corePoolSize是10,那麼確定沒達到了,因此直接會在線程池裏建立一個線程出來而後執行這個任務,以下圖。

接着假如說,這個線程處理完一個任務了,那麼此時線程是不會被銷燬的,他會一直等待下一個提交過來的任務。

那麼,究竟是怎麼等待的呢?

很簡單,線程池會搭配一個workQueue,好比這裏搭配的就是一個無界的LinkedBlockingQueue,幾乎能夠無限量放入任務。

而後那個線程處理完一個任務以後,就會用阻塞的方式嘗試從任務隊列裏獲取任務,若是隊列是空的,他就會阻塞卡在那兒不動,直到有人放一個任務到隊列裏,他纔會獲取到一個任務而後繼續執行,循環往復,以下圖。

接着再次提交任務,線程池一判斷髮現,誒?好像線程數量才只有1個,徹底比corePoolSize(10個)要小,那麼繼續直接在池子裏建立一個線程,而後處理這個任務,處理完了繼續嘗試從workQueue裏阻塞式獲取任務。

一直重複上面的操做,直到線程池裏有10個線程了,達到了corePoolSize指定的數量,以下圖。

這個時候你若是再提交任務,他一會兒發現,誒?不對啊,線程池裏已經有10個線程了,跟corePoolSize指定的線程數量同樣了。

那麼如今,我就不須要建立任何一個額外的線程了,如今你只要提交任務,所有直接入隊到workQueue裏就好。

此時線程池裏的線程都阻塞式在workQueue上等待獲取任務,有一個任務進來就會喚醒一個線程來處理這個任務,處理完了任務再次阻塞在workQueue上嘗試獲取下一個任務,以下圖所示這個意思。

這裏咱們看到他用的是一個無界的LinkedBlockingQueue,可是假如說他用的是一個有界的隊列呢?

好比說限定好了隊列最多隻能放10個任務,那麼假如說,線程池裏的線程來不及處理任務了,而後隊列一會兒放滿了10個任務。

此時就會出現任務入隊的失敗,由於隊列滿了,沒法入隊。

而後就會嘗試再次在線程池裏建立線程,這個時候就會一直建立線程直到線程池裏的線程數量達到maximumPoolSize指定的數量爲止。

雖然這裏fixed線程池默認corePoolSize和maximumPoolSize的數量都是一致的,可是能夠假設此時maximumPoolSize的數量是20呢?

那麼就會繼續建立線程,直到線程數量達到20個,而後用額外建立的10個線程在隊列滿的狀況下,繼續處理任務。

整個過程,以下圖所示:

接着萬一隊列滿了,而後線程池的線程數量達到了maximumPoolSize指定的數量了,你額外建立線程都沒法建立了,此時會如何呢?

答案是:會reject掉,不讓你繼續提交任務了,此時默認的就是拋出一個異常。

那麼,在上圖中額外建立出來的,超出corePoolSize的那些線程呢?

他們一旦建立出來以後,會發現線程池數量已經超過corePoolSize了,此時他們會嘗試等待workQueue裏的任務。

一旦超過keepAliveTime指定的時間,還獲取不到任務,好比keepAliveTime是60秒,那麼假如超過60秒獲取不到任務,他就會自動釋放掉了,這個線程就銷燬了。

整個過程,以下圖所示。

(4)無界隊列引起的內存飆升

明白了線程池的運行原理了,這個面試題就好解答了。

咱們以最經常使用的fixed線程池舉例,他的線程池數量是固定的,由於他用的是近乎於無界的LinkedBlockingQueue,幾乎能夠無限制的放入任務到隊列裏。

因此只要線程池裏的線程數量達到了corePoolSize指定的數量以後,接下來就維持這個固定數量的線程了。

而後,全部任務都會入隊到workQueue裏去,線程從workQueue獲取任務來處理。

這個隊列幾乎永遠不會滿,固然這是幾乎,由於LinkedBlockingQueue默認的最大任務數量是Integer.MAX_VALUE,很是大,近乎於能夠理解爲無限吧。

只要隊列不滿,就跟maximumPoolSize、keepAliveTime這些不要緊了,由於不會建立超過corePoolSize數量的線程的。

一樣,給你們來一張圖,咱們來看看:

那麼此時萬一每一個線程獲取到一個任務以後,他處理的時間特別特別的長,長到了使人髮指的地步。好比處理一個任務要幾個小時,此時會如何?

固然會出現workQueue裏不斷的積壓愈來愈多得任務,不停的增長。

這個過程當中會致使機器的內存使用不停的飆升,最後也許極端狀況下就致使JVM OOM了,系統就掛掉了。

因此這就是這個面試題背後你要知道的線程池的運行原理,以及可能遇到的一些問題,你們要作到內心有數。

END

掃描下方二維碼,備註:「資料」,獲取更多「祕製」 精品學習資料

若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!

一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上

歡迎掃描下方二維碼,持續關注:

石杉的架構筆記(id:shishan100)

十餘年BAT架構經驗傾囊相授

推薦閱讀:

一、拜託!面試請不要再問我Spring Cloud底層原理

二、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?

三、【性能優化之道】每秒上萬併發下的Spring Cloud參數優化實戰

四、微服務架構如何保障雙11狂歡下的99.99%高可用

五、兄弟,用大白話告訴你小白都能聽懂的Hadoop架構原理

六、大規模集羣下Hadoop NameNode如何承載每秒上千次的高併發訪問

七、【性能優化的祕密】Hadoop如何將TB級大文件的上傳性能優化上百倍

八、拜託,面試請不要再問我TCC分佈式事務的實現原理!

九、【坑爹呀!】最終一致性分佈式事務如何保障實際生產中99.99%高可用?

十、拜託,面試請不要再問我Redis分佈式鎖的實現原理!

十一、【眼前一亮!】看Hadoop底層算法如何優雅的將大規模集羣性能提高10倍以上?

十二、億級流量系統架構之如何支撐百億級數據的存儲與計算

1三、億級流量系統架構之如何設計高容錯分佈式計算系統

1四、億級流量系統架構之如何設計承載百億流量的高性能架構

1五、億級流量系統架構之如何設計每秒十萬查詢的高併發架構

1六、億級流量系統架構之如何設計全鏈路99.99%高可用架構

1七、七張圖完全講清楚ZooKeeper分佈式鎖的實現原理

1八、大白話聊聊Java併發面試問題之volatile究竟是什麼?

1九、大白話聊聊Java併發面試問題之Java 8如何優化CAS性能?

20、大白話聊聊Java併發面試問題之談談你對AQS的理解?

2一、大白話聊聊Java併發面試問題之公平鎖與非公平鎖是啥?

2二、大白話聊聊Java併發面試問題之微服務註冊中心的讀寫鎖優化

2三、互聯網公司的面試官是如何360°無死角考察候選人的?(上篇)

2四、互聯網公司面試官是如何360°無死角考察候選人的?(下篇)

2五、Java進階面試系列之一:哥們,大家的系統架構中爲何要引入消息中間件?

2六、【Java進階面試系列之二】:哥們,那你說說系統架構引入消息中間件有什麼缺點?

2七、【行走的Offer收割機】記一位朋友斬獲BAT技術專家Offer的面試經歷

2八、【Java進階面試系列之三】哥們,消息中間件在大家項目裏是如何落地的?

2九、【Java進階面試系列之四】扎心!線上服務宕機時,如何保證數據100%不丟失?

30、一次JVM FullGC的背後,竟隱藏着驚心動魄的線上生產事故!

3一、【高併發優化實踐】10倍請求壓力來襲,你的系統會被擊垮嗎?

3二、【Java進階面試系列之五】消息中間件集羣崩潰,如何保證百萬生產數據不丟失?

3三、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(上)?

3四、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(中)?

3五、億級流量系統架構之如何在上萬併發場景下設計可擴展架構(下)?

3六、億級流量架構第二彈:你的系統真的無懈可擊嗎?

3七、億級流量系統架構之如何保證百億流量下的數據一致性(上)

3八、億級流量系統架構之如何保證百億流量下的數據一致性(中)?

3九、億級流量系統架構之如何保證百億流量下的數據一致性(下)?

40、互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(1)

4一、互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(2

4二、面試大殺器:消息中間件如何實現消費吞吐量的百倍優化?

4三、高併發場景下,如何保證生產者投遞到消息中間件的消息不丟失?

4四、兄弟,用大白話給你講小白都能看懂的分佈式系統容錯架構

4五、從團隊自研的百萬併發中間件系統的內核設計看Java併發性能優化

4六、【非廣告,純乾貨】英語差的程序員如何才能無障礙閱讀官方文檔?

4七、若是20萬用戶同時訪問一個熱點緩存,如何優化你的緩存架構?

4八、【非廣告,純乾貨】中小公司的Java工程師應該如何逆襲衝進BAT?

4九、拜託,面試請不要再問我分佈式搜索引擎的架構原理!

做者:石杉的架構筆記 連接:juejin.im/post/5c263a… 來源:掘金 著做權歸做者全部,轉載請聯繫做者得到受權!

相關文章
相關標籤/搜索