線程池的好處:數組
第一:下降資源消耗。經過重複利用已建立的線程下降線程建立和銷燬形成的消耗。緩存
第二:提升響應速度。當任務到達時,任務能夠不須要的等到線程建立就能當即執行。服務器
第三:提升線程的可管理性。線程是稀缺資源,若是無限制的建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配,調優和監控。可是要作到合理的利用線程池,必須對其原理了如指掌。併發
咱們能夠經過ThreadPoolExecutor來建立一個線程池。異步
1 |
new ThreadPoolExecutor(corePoolSize, maximumPoolSize, |
2 |
keepAliveTime, milliseconds,runnableTaskQueue, threadFactory,handler); |
建立一個線程池須要輸入幾個參數:spa
RejectedExecutionHandler(飽和策略):當隊列和線程池都滿了,說明線程池處於飽和狀態,那麼必須採起一種策略處理提交的新任務。這個策略默認狀況下是AbortPolicy,表示沒法處理新任務時拋出異常。如下是JDK1.5提供的四種策略。n AbortPolicy:直接拋出異常。線程
線程池的executor,submit區別在於,execute不用返回結果,submit返回furture包裝的結果值rest
shutdown:shutdown的原理是隻是將線程池的狀態設置成SHUTDOWN狀態,而後中斷全部沒有正在執行任務的線程日誌
shutdownNow:shutdownNow的原理是遍歷線程池中的工做線程,而後逐個調用線程的interrupt方法來中斷線程,因此沒法響應中斷的任務可能永遠沒法終止。shutdownNow會首先將線程池的狀態設置成STOP,而後嘗試中止全部的正在執行或暫停任務的線程,並返回等待執行任務的列表。code
只要調用了這兩個關閉方法的其中一個,isShutdown方法就會返回true。當全部的任務都已關閉後,才表示線程池關閉成功,這時調用isTerminaed方法會返回true。至於咱們應該調用哪種方法來關閉線程池,應該由提交到線程池的任務特性決定,一般調用shutdown來關閉線程池,若是任務不必定要執行完,則能夠調用shutdownNow。
流程分析:線程池的主要工做流程以下圖:
從上圖咱們能夠看出,當提交一個新任務到線程池時,線程池的處理流程以下:
一:newCachedThreadPool-可變尺寸的線程池(緩存線程池)
(1)緩存型池子,先查看池中有沒有之前創建的線程,若是有,就reuse(重用),若是沒有,就創建一個新的線程加入池中;
(2)緩存型池子,一般用於執行一些生存週期很短的異步型任務;所以一些面向鏈接的daemon型server中用得很少;
(3)能reuse(重用)的線程,必須是timeout IDLE內的池中線程,缺省timeout是60s,超過這個IDLE時長,線程實例將被終止及移出池;
(4)注意,放入CachedThreadPool的線程沒必要擔憂其結束,超過TIMEOUT不活動,其會自動被終止。
二:newFixedThreadPool-固定大小的線程池
(1)newFixedThreadPool與cacheThreadPool差很少,也是能reuse就用,但不能隨時建新的線程;
(2)其獨特之處:任意時間點,最多隻能有固定數目的活動線程存在,此時若是有新的線程要創建,只能放在另外的隊列中等待,直到當前的線程中某個線程終止直接被移出池子;
(3)和cacheThreadPool不一樣,FixedThreadPool沒有IDLE機制(可能也有,但既然文檔沒提,確定很是長,相似依賴上層的TCP或UDP IDLE機制之類的),因此FixedThreadPool多數針對一些很穩定很固定的正規併發線程,多用於服務器;
(4)從方法的源代碼看,cache池和fixed池調用的是同一個底層池,只不過參數不一樣:
fixed池線程數固定,而且是0秒IDLE(無IDLE);
cache池線程數支持0-Integer.MAX_VALUE(顯然徹底沒考慮主機的資源承受能力),60秒IDLE。
三:ScheduledThreadPool-調度線程池
(1)調度型線程池;
(2)這個池子裏的線程能夠按schedule依次delay執行,或週期執行。
四:SingleThreadExecutor-單例線程池
(1)單例線程,任意時間池中只能有一個線程; (2)用的是和cache池和fixed池相同的底層池,但線程數目是1-1,0秒IDLE(無IDLE)。