真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

本篇內(nèi)容主要講解“使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣”吧!

廣德ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷(xiāo)售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話(huà)聯(lián)系或者加微信:13518219792(備注:SSL證書(shū)合作)期待與您的合作!

(1)背景引入

今天跟大家聊一個(gè)互聯(lián)網(wǎng)大廠的Java面試題:使用無(wú)界隊(duì)列的線程池會(huì)導(dǎo)致內(nèi)存飆升嗎?

因?yàn)樵诿婊ヂ?lián)網(wǎng)大廠的時(shí)候,一定會(huì)問(wèn)并發(fā),問(wèn)并發(fā)的時(shí)候一定會(huì)問(wèn)到線程池,問(wèn)到線程池一定會(huì)問(wèn)構(gòu)造線程池的一些參數(shù)的含義。

然后,有一些面試官會(huì)就線程池的具體場(chǎng)景,問(wèn)一些可能會(huì)遇到的問(wèn)題。

所以,在這里就可能有上述那樣一個(gè)面試中的問(wèn)題,算是Java面試?yán)锵鄬?duì)來(lái)說(shuō)高階一點(diǎn)的。

我相信大家一定起碼知道線程池是個(gè)什么東西的。簡(jiǎn)單來(lái)說(shuō),就是維護(hù)一個(gè)池子,池子里面放了很多的線程。

然后來(lái)一個(gè)任務(wù),某個(gè)線程就獲取這個(gè)任務(wù)來(lái)執(zhí)行,任務(wù)執(zhí)行完之后線程是不會(huì)釋放掉的,而是停留在線程池里繼續(xù)等待下一個(gè)任務(wù)。

這樣的一個(gè)好處是你沒(méi)必要自己手動(dòng)頻繁的創(chuàng)建和銷(xiāo)毀線程,畢竟線程是較重的資源,頻繁的創(chuàng)建和銷(xiāo)毀對(duì)系統(tǒng)性能是沒(méi)好處的。

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

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

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

那么平時(shí)在Java里寫(xiě)代碼的時(shí)候,大家記得不記得線程池是如何構(gòu)造出來(lái)的呢?

是不是類(lèi)似下面那樣的代碼,比如說(shuō)我們構(gòu)造一個(gè)線程數(shù)量固定的一個(gè)線程池:

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

那么Executors.newFixedThreadPool(10)內(nèi)部到底又是如何構(gòu)造出來(lái)線程池的呢?

其實(shí)很簡(jiǎn)單,翻開(kāi)JDK源碼就可以看到里面的代碼如下:

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

簡(jiǎn)單來(lái)說(shuō),就是構(gòu)造了一個(gè)ThreadPoolExecutor對(duì)象實(shí)例,你大致就認(rèn)為他是一個(gè)線程池吧,傳入了一些參數(shù),這些參數(shù)大致包含了:

  1  ·   corePoolSize

  2  ·   maximumPoolSize

  3  ·   keepAliveTime

  4  · workQueue

假如說(shuō)我們構(gòu)造線程池傳入的線程數(shù)量是10,那么在這里,corePoolSize和maximumSize都是10,keepAliveTime默認(rèn)就是0,workQueue是一個(gè)無(wú)界的LinkedBlockingQueue。

接下來(lái),我們具體來(lái)看看構(gòu)造一個(gè)線程池傳入一些參數(shù)之后,具體這個(gè)線程池的運(yùn)行原理是什么。

(3)線程池的運(yùn)行原理

簡(jiǎn)單來(lái)說(shuō),剛開(kāi)始的時(shí)候其實(shí)線程池里是空的,就是一個(gè)線程都沒(méi)有的,如下圖所示。

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

接著如果你使用線程池提交一個(gè)任務(wù)進(jìn)去,希望由線程池里的一個(gè)線程來(lái)執(zhí)行,如下代碼所示,就是提交一個(gè)任務(wù):

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

這個(gè)時(shí)候,線程池會(huì)先看一下,現(xiàn)在池子里的線程數(shù)量有沒(méi)有有達(dá)到corePoolSize指定的數(shù)量。

現(xiàn)在線程池里的線程數(shù)量是0,然后corePoolSize是10,那么肯定沒(méi)達(dá)到了,所以直接會(huì)在線程池里創(chuàng)建一個(gè)線程出來(lái)然后執(zhí)行這個(gè)任務(wù),如下圖。

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

接著假如說(shuō),這個(gè)線程處理完一個(gè)任務(wù)了,那么此時(shí)線程是不會(huì)被銷(xiāo)毀的,他會(huì)一直等待下一個(gè)提交過(guò)來(lái)的任務(wù)。

那么,到底是怎么等待的呢?

很簡(jiǎn)單,線程池會(huì)搭配一個(gè)workQueue,比如這里搭配的就是一個(gè)無(wú)界的LinkedBlockingQueue,幾乎可以無(wú)限量放入任務(wù)。

然后那個(gè)線程處理完一個(gè)任務(wù)之后,就會(huì)用阻塞的方式嘗試從任務(wù)隊(duì)列里獲取任務(wù),如果隊(duì)列是空的,他就會(huì)阻塞卡在那兒不動(dòng),直到有人放一個(gè)任務(wù)到隊(duì)列里,他才會(huì)獲取到一個(gè)任務(wù)然后繼續(xù)執(zhí)行,循環(huán)往復(fù),如下圖。

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

接著再次提交任務(wù),線程池一判斷發(fā)現(xiàn),誒?好像線程數(shù)量才只有1個(gè),完全比corePoolSize(10個(gè))要小,那么繼續(xù)直接在池子里創(chuàng)建一個(gè)線程,然后處理這個(gè)任務(wù),處理完了繼續(xù)嘗試從workQueue里阻塞式獲取任務(wù)。

一直重復(fù)上面的操作,直到線程池里有10個(gè)線程了,達(dá)到了corePoolSize指定的數(shù)量,如下圖。

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

這個(gè)時(shí)候你如果再提交任務(wù),他一下子發(fā)現(xiàn),誒?不對(duì)啊,線程池里已經(jīng)有10個(gè)線程了,跟corePoolSize指定的線程數(shù)量一樣了。

那么現(xiàn)在,我就不需要?jiǎng)?chuàng)建任何一個(gè)額外的線程了,現(xiàn)在你只要提交任務(wù),全部直接入隊(duì)到workQueue里就好。

此時(shí)線程池里的線程都阻塞式在workQueue上等待獲取任務(wù),有一個(gè)任務(wù)進(jìn)來(lái)就會(huì)喚醒一個(gè)線程來(lái)處理這個(gè)任務(wù),處理完了任務(wù)再次阻塞在workQueue上嘗試獲取下一個(gè)任務(wù),如下圖所示這個(gè)意思。

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

這里我們看到他用的是一個(gè)無(wú)界的LinkedBlockingQueue,但是假如說(shuō)他用的是一個(gè)有界的隊(duì)列呢?

比如說(shuō)限定好了隊(duì)列最多只能放10個(gè)任務(wù),那么假如說(shuō),線程池里的線程來(lái)不及處理任務(wù)了,然后隊(duì)列一下子放滿(mǎn)了10個(gè)任務(wù)。

此時(shí)就會(huì)出現(xiàn)任務(wù)入隊(duì)的失敗,因?yàn)殛?duì)列滿(mǎn)了,無(wú)法入隊(duì)。

然后就會(huì)嘗試再次在線程池里創(chuàng)建線程,這個(gè)時(shí)候就會(huì)一直創(chuàng)建線程直到線程池里的線程數(shù)量達(dá)到maximumPoolSize指定的數(shù)量為止。

雖然這里fixed線程池默認(rèn)corePoolSize和maximumPoolSize的數(shù)量都是一致的,但是可以假設(shè)此時(shí)maximumPoolSize的數(shù)量是20呢?

那么就會(huì)繼續(xù)創(chuàng)建線程,直到線程數(shù)量達(dá)到20個(gè),然后用額外創(chuàng)建的10個(gè)線程在隊(duì)列滿(mǎn)的情況下,繼續(xù)處理任務(wù)。

整個(gè)過(guò)程,如下圖所示:

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

接著萬(wàn)一隊(duì)列滿(mǎn)了,然后線程池的線程數(shù)量達(dá)到了maximumPoolSize指定的數(shù)量了,你額外創(chuàng)建線程都無(wú)法創(chuàng)建了,此時(shí)會(huì)如何呢?

答案是:會(huì)reject掉,不讓你繼續(xù)提交任務(wù)了,此時(shí)默認(rèn)的就是拋出一個(gè)異常。

那么,在上圖中額外創(chuàng)建出來(lái)的,超出corePoolSize的那些線程呢?

他們一旦創(chuàng)建出來(lái)之后,會(huì)發(fā)現(xiàn)線程池?cái)?shù)量已經(jīng)超過(guò)corePoolSize了,此時(shí)他們會(huì)嘗試等待workQueue里的任務(wù)。

一旦超過(guò)keepAliveTime指定的時(shí)間,還獲取不到任務(wù),比如keepAliveTime是60秒,那么假如超過(guò)60秒獲取不到任務(wù),他就會(huì)自動(dòng)釋放掉了,這個(gè)線程就銷(xiāo)毀了。

整個(gè)過(guò)程,如下圖所示。

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

(4)無(wú)界隊(duì)列引發(fā)的內(nèi)存飆升

明白了線程池的運(yùn)行原理了,這個(gè)面試題就好解答了。

我們以最常用的fixed線程池舉例,他的線程池?cái)?shù)量是固定的,因?yàn)樗玫氖墙跤跓o(wú)界的LinkedBlockingQueue,幾乎可以無(wú)限制的放入任務(wù)到隊(duì)列里。

所以只要線程池里的線程數(shù)量達(dá)到了corePoolSize指定的數(shù)量之后,接下來(lái)就維持這個(gè)固定數(shù)量的線程了。

然后,所有任務(wù)都會(huì)入隊(duì)到workQueue里去,線程從workQueue獲取任務(wù)來(lái)處理。

這個(gè)隊(duì)列幾乎永遠(yuǎn)不會(huì)滿(mǎn),當(dāng)然這是幾乎,因?yàn)長(zhǎng)inkedBlockingQueue默認(rèn)的最大任務(wù)數(shù)量是Integer.MAX_VALUE,非常大,近乎于可以理解為無(wú)限吧。

只要隊(duì)列不滿(mǎn),就跟maximumPoolSize、keepAliveTime這些沒(méi)關(guān)系了,因?yàn)椴粫?huì)創(chuàng)建超過(guò)corePoolSize數(shù)量的線程的。

同樣,給大家來(lái)一張圖,我們來(lái)看看:

使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣

那么此時(shí)萬(wàn)一每個(gè)線程獲取到一個(gè)任務(wù)之后,他處理的時(shí)間特別特別的長(zhǎng),長(zhǎng)到了令人發(fā)指的地步。比如處理一個(gè)任務(wù)要幾個(gè)小時(shí),此時(shí)會(huì)如何?

當(dāng)然會(huì)出現(xiàn)workQueue里不斷的積壓越來(lái)越多得任務(wù),不停的增加。

這個(gè)過(guò)程中會(huì)導(dǎo)致機(jī)器的內(nèi)存使用不停的飆升,最后也許極端情況下就導(dǎo)致JVM OOM了,系統(tǒng)就掛掉了。

所以這就是這個(gè)面試題背后你要知道的線程池的運(yùn)行原理,以及可能遇到的一些問(wèn)題,大家要做到心里有數(shù)。

到此,相信大家對(duì)“使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!


網(wǎng)頁(yè)標(biāo)題:使用Java無(wú)界隊(duì)列的線程池會(huì)怎么樣
文章鏈接:http://weahome.cn/article/gehdde.html

其他資訊

在線咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部