線程池是一種線程的使用模式,爲了減少線程使用中頻繁創建與銷燬的資源消耗代價。
相比於來一個任務創建一個線程的方式,使用線程池的優勢體現在如下幾點:
- 避免了線程的重複創建與開銷帶來的資源消耗代價
- 提升了任務響應速度,任務來了直接選一個線程執行而無需等待線程的創建
- 線程的統一分配和管理,也方便統一的監控和調優
基本介紹
在正式介紹線程池相關概念之前,我們先看一張線程池相關接口的類圖結構。
右上角的幾個接口可以先不看,等我們介紹到組合任務的時候會繼續說的,我們看左邊,Executor、ExecutorService 以及 AbstractExecutorService 都是我們熟悉的,它們抽象了任務執行者的基本模型。
ThreadPoolExecutor 是對線程池概念的抽象,它天生實現了任務執行的相關接口,也就是說,線程池也是一個任務的執行者,允許你向其中提交多個任務,線程池將負責分配線程與調度任務。
至於 Schedule 線程池,它是擴展了基礎的線程池實現,提供「計劃調度」能力,定時調度任務,延時執行等。
ThreadPoolExecutor類
線程池的創建
線程池的創建主要看這七個構造參數:
- corePoolSize:核心線程數。核心線程會一直存活,即使沒有任務需要執行。當線程數小於核心線程數時,即使有線程空閒,線程池也會優先創建新線程處理。設置allowCoreThreadTimeout=true(默認false)時,核心線程會超時關閉。
- bloackQueue:阻塞隊列。當核心線程數達到最大時,新任務會放在隊列中排隊等待執行。
- maxPoolSize:最大線程數。當線程數>=corePoolSize + queueCapacity,線程池會創建新線程來處理任務。當線程數>=maxPoolSize +queueCapacity,線程池會執行拒絕策略。
- keepAliveTime:線程空閒時間。當線程空閒時間達到keepAliveTime時,線程會退出,直到線程數量=corePoolSize。如果allowCoreThreadTimeout=true,則會直到線程數量=0。
- unit:線程空閒時間單位。
- threadFactory:創建線程工廠類
- rejectedExecutionHandler:任務拒絕處理器。兩種情況會拒絕處理任務:(1)當線程數已經達到maxPoolSize,切隊列已滿,會拒絕新任務。(2)當線程池被調用shutdown()後,會等待線程池裏的任務執行完畢,再shutdown。
線程池執行方式
threadPoolExcutor.execute()
接收一個Runnable實現類,線程池直接執行任務,沒有返回值
threadPoolExcutor.submit()
接收一個Callable對象,線程池執行任務,並返回一個Futured對象,用來接收執行結果。
線程池的關閉
- shutDownNow():線程池拒接收新提交的任務,同時立馬關閉線程池,線程池裏的任務不再執行。
- shutDown():線程池拒接收新提交的任務,同時等待線程池裏的任務執行完畢後關閉線程池。
- allowCoreThreadTimeOut(true):允許核心線程銷燬,但這只是線程的銷燬,線程池仍存在。
1.2情況下,再調用threadPoolExcutor.execute()會拋異常,因爲該線程池已被銷燬,不可再建線程執行;3情況下調用threadPoolExcutor.execute()可再次創建被銷燬的線程,並執行,因此3並不算做線程池的關閉,但它確實可以註銷所有線程。