1. 為什么要用線程池?
可以通過(guò)復(fù)用已創(chuàng)建的線程來(lái)降低資源消耗; 需要用線程的時(shí)候可以從線程池中取出直接用,而不需要等待線程的創(chuàng)建; 可以對(duì)線程統(tǒng)一調(diào)度、管理和監(jiān)控。
2. 線程池有哪些狀態(tài)?
running,運(yùn)行狀態(tài); shutdown,不接受新任務(wù)的提交,但隊(duì)列中的任務(wù)會(huì)處理完; stop,不接受新任務(wù)的提交,當(dāng)前執(zhí)行的任務(wù)也會(huì)立即終止; tidying,shutdown狀態(tài)下任務(wù)隊(duì)列為空了就會(huì)變成tidying狀態(tài),進(jìn)入此狀態(tài)后會(huì)執(zhí)行 terminate 方法; terminated,線程池徹底終止,tidying狀態(tài)下執(zhí)行了 terminate 方法就會(huì)進(jìn)入此狀態(tài)。
3. 常見的線程池有哪些?他們有什么缺點(diǎn)嗎?
newFixedThreadPool,線程數(shù)固定的線程池。任務(wù)隊(duì)列用的是 LinkedBlockingQueue,該阻塞隊(duì)列的最大容量是 int 的最大值,21億左右,可能會(huì)造成 OOM; newSingleThreadExecutor,只有一個(gè)線程的線程池。任務(wù)隊(duì)列也是 LinkedBlockingQueue,可能造成 OOM; newCachedThreadPool,帶緩沖的線程池,線程數(shù)量不固定。允許的最大線程數(shù)是 int 最大值,所以也可能會(huì) OOM。
4. 你在工作中是如何使用線程池的呢?
常見線程池都可能會(huì)造成 OOM,所以應(yīng)該自己創(chuàng)建。
5. 自己創(chuàng)建線程池有幾個(gè)參數(shù)?代表什么意思?要怎么設(shè)置呢?
有七個(gè)參數(shù):
corePoolSize:核心線程數(shù),相當(dāng)于銀行今天當(dāng)值窗口數(shù); maximumPoolSize:最大線程數(shù),相當(dāng)于銀行的窗口總數(shù); keepAliveTime:多余空閑線程存活的時(shí)間; unit:多于空閑線程存活時(shí)間的單位; workQueue:等待隊(duì)列; threadFactory:創(chuàng)建線程的工廠; handler:拒絕策略,任務(wù)隊(duì)列滿了的時(shí)候?qū)π逻M(jìn)來(lái)的任務(wù)的處理方式。
6. 線程池有哪些拒絕策略?
AbortPolicy:拋出異常; CallerRunsPolicy:任務(wù)回退到調(diào)用者; DiscardOldestPolicy:丟棄掉等待最久的任務(wù); DiscardPolicy:丟棄掉任務(wù)。
7. 線程池的 submit 和 execute 有什么區(qū)別?
submit 可以執(zhí)行 runnable 和 callable 任務(wù),有 future 返回值; execute 只能執(zhí)行 runnable 任務(wù),沒有返回值。
8. shutdown 和 shutdownNow 有什么區(qū)別?
shutdown 不會(huì)立即終止線程池,會(huì)等待任務(wù)隊(duì)列中的任務(wù)執(zhí)行完; shutdownNow 會(huì)試圖立即終止線程池,如果還有正在執(zhí)行的任務(wù),則會(huì)拋出 sleep interrupt 的異常。
9. 清楚線程池的工作原理嗎?
一個(gè)任務(wù)進(jìn)來(lái)的時(shí)候,如果有空閑線程,就用空閑線程執(zhí)行該任務(wù);如果沒有,就看當(dāng)前線程數(shù)是否超過(guò)核心線程數(shù),如果沒超過(guò),就創(chuàng)建新線程執(zhí)行任務(wù);如果超過(guò)了,就進(jìn)入任務(wù)隊(duì)列進(jìn)行等待;如果任務(wù)隊(duì)列滿了,就會(huì)判斷當(dāng)前線程數(shù)是否超過(guò)了最大允許的線程數(shù),如果沒超過(guò),就會(huì)創(chuàng)建新線程執(zhí)行任務(wù),如果超過(guò)了,就會(huì)執(zhí)行對(duì)應(yīng)的拒絕策略。
10. 核心線程數(shù)設(shè)置為多少合適呢?
如果機(jī)器的 CPU 處理能力很強(qiáng),但是磁盤讀寫能力不強(qiáng),這叫 IO密集型,這種情況線程數(shù)可以設(shè)置多一點(diǎn),充分利用 CPU,一般設(shè)置為 CPU核數(shù)的兩倍; 如果機(jī)器的 CPU 比較弱,磁盤讀寫能力比較強(qiáng),這叫 CPU 密集型,這種情況線程數(shù)應(yīng)該少一點(diǎn),避免 CPU 過(guò)度切換,一般設(shè)置為 CPU 核數(shù)加一。
11. 線程池為什么要用阻塞隊(duì)列?
阻塞隊(duì)列可以在隊(duì)列中沒有任務(wù)時(shí)阻塞獲取任務(wù)的線程,進(jìn)入 wait 狀態(tài),釋放 CPU 資源,隊(duì)列中任務(wù)滿了就會(huì)阻塞將任務(wù)入隊(duì)的線程,使線程池可以執(zhí)行相關(guān)的拒絕策略。
12. 線程池線程復(fù)用的原理是什么?
將線程和任務(wù)解耦,而不是一個(gè)任務(wù)進(jìn)來(lái)就創(chuàng)建一個(gè)線程去執(zhí)行;線程池中的每個(gè)線程啟動(dòng)后,都循環(huán)地去判斷有沒有任務(wù)要執(zhí)行,有就在 run 方法中去執(zhí)行。
13. 你們項(xiàng)目哪些地方用到了線程池?
比如我們系統(tǒng)會(huì)用線程池創(chuàng)建多個(gè)線程同時(shí)去讀取郵件或者短信表,多個(gè)線程同時(shí)去發(fā)郵件或短信。
掃描二維碼
聯(lián)系客服