歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)程序員
週一至週五早8點半!精品技術文章準時送上!面試
(1)背景引入算法
(2)線程池是如何構造的?緩存
(3)線程池的運行原理性能優化
(4)無界隊列引起的內存飆升架構
今天跟你們聊一個互聯網大廠的Java面試題:使用無界隊列的線程池會致使內存飆升嗎?併發
由於在面互聯網大廠的時候,必定會問併發,問併發的時候必定會問到線程池,問到線程池必定會問構造線程池的一些參數的含義。分佈式
而後,有一些面試官會就線程池的具體場景,問一些可能會遇到的問題。微服務
因此,在這裏就可能有上述那樣一個面試中的問題,算是Java面試裏相對來講高階一點的。高併發
我相信你們必定起碼知道線程池是個什麼東西的。簡單來講,就是維護一個池子,池子裏面放了不少的線程。
而後來一個任務,某個線程就獲取這個任務來執行,任務執行完以後線程是不會釋放掉的,而是停留在線程池裏繼續等待下一個任務。
這樣的一個好處是你不必本身手動頻繁的建立和銷燬線程,畢竟線程是較重的資源,頻繁的建立和銷燬對系統性能是沒好處的。
咱們看看下面的圖,回顧一下線程池的含義。
那麼平時在Java裏寫代碼的時候,你們記得不記得線程池是如何構造出來的呢?
是否是相似下面那樣的代碼,好比說咱們構造一個線程數量固定的一個線程池:
那麼Executors.newFixedThreadPool(10)內部到底又是如何構造出來線程池的呢?其實很簡單,翻開JDK源碼就能夠看到裏面的代碼以下:
簡單來講,就是構造了一個ThreadPoolExecutor對象實例,你大體就認爲他是一個線程池吧,傳入了一些參數,這些參數大體包含了:corePoolSize maximumPoolSize keepAliveTime workQueue
假如說咱們構造線程池傳入的線程數量是10,那麼在這裏,corePoolSize和maximumSize都是10,keepAliveTime默認就是0,workQueue是一個無界的LinkedBlockingQueue。
接下來,咱們具體來看看構造一個線程池傳入一些參數以後,具體這個線程池的運行原理是什麼。
簡單來講,剛開始的時候其實線程池裏是空的,就是一個線程都沒有的,以下圖所示。
接着若是你使用線程池提交一個任務進去,但願由線程池裏的一個線程來執行,以下代碼所示,就是提交一個任務:
這個時候,線程池會先看一下,如今池子裏的線程數量有沒有有達到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秒獲取不到任務,他就會自動釋放掉了,這個線程就銷燬了。
整個過程,以下圖所示。
明白了線程池的運行原理了,這個面試題就好解答了。
咱們以最經常使用的fixed線程池舉例,他的線程池數量是固定的,由於他用的是近乎於無界的LinkedBlockingQueue,幾乎能夠無限制的放入任務到隊列裏。
因此只要線程池裏的線程數量達到了corePoolSize指定的數量以後,接下來就維持這個固定數量的線程了。
而後,全部任務都會入隊到workQueue裏去,線程從workQueue獲取任務來處理。
這個隊列幾乎永遠不會滿,固然這是幾乎,由於LinkedBlockingQueue默認的最大任務數量是Integer.MAX_VALUE,很是大,近乎於能夠理解爲無限吧。
只要隊列不滿,就跟maximumPoolSize、keepAliveTime這些不要緊了,由於不會建立超過corePoolSize數量的線程的。
一樣,給你們來一張圖,咱們來看看:
那麼此時萬一每一個線程獲取到一個任務以後,他處理的時間特別特別的長,長到了使人髮指的地步。好比處理一個任務要幾個小時,此時會如何?
固然會出現workQueue裏不斷的積壓愈來愈多得任務,不停的增長。
這個過程當中會致使機器的內存使用不停的飆升,最後也許極端狀況下就致使JVM OOM了,系統就掛掉了。
因此這就是這個面試題背後你要知道的線程池的運行原理,以及可能遇到的一些問題,你們要作到內心有數。
掃描下方二維碼,備註:「資料」,獲取更多「祕製」 精品學習資料
若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!
一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上
歡迎掃描下方二維碼,持續關注:
石杉的架構筆記(id:shishan100)
十餘年BAT架構經驗傾囊相授
推薦閱讀:
二、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?
三、【性能優化之道】每秒上萬併發下的Spring Cloud參數優化實戰
六、大規模集羣下Hadoop NameNode如何承載每秒上千次的高併發訪問
七、【性能優化的祕密】Hadoop如何將TB級大文件的上傳性能優化上百倍
九、【坑爹呀!】最終一致性分佈式事務如何保障實際生產中99.99%高可用?
十一、【眼前一亮!】看Hadoop底層算法如何優雅的將大規模集羣性能提高10倍以上?
1六、億級流量系統架構之如何設計全鏈路99.99%高可用架構
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九、億級流量系統架構之如何保證百億流量下的數據一致性(下)?
40、互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(1)
4一、互聯網面試必殺:如何保證消息中間件全鏈路數據100%不丟失(2)
4三、高併發場景下,如何保證生產者投遞到消息中間件的消息不丟失?
4五、從團隊自研的百萬併發中間件系統的內核設計看Java併發性能優化
4六、【非廣告,純乾貨】英語差的程序員如何才能無障礙閱讀官方文檔?
4七、若是20萬用戶同時訪問一個熱點緩存,如何優化你的緩存架構?
4八、【非廣告,純乾貨】中小公司的Java工程師應該如何逆襲衝進BAT?
做者:石杉的架構筆記 連接:juejin.im/post/5c263a… 來源:掘金 著做權歸做者全部,轉載請聯繫做者得到受權!