概述
線程池是管理java線程生命周期的工具
- 降低資源消耗。通過池化技術能夠重復利用已創建的線程,降低線程頻繁創建和銷毀造成的資源消耗
- 提高線程的可管理性。無需程序員手動銷毀線程,控制線程創建的數量,避免無限制的創建影響系統穩定性
線程池的運行機制
線程池的核心參數
- corePoolSize(必需):核心線程數量。默認情況下,核心線程會一直存活,但是當allowCoreThreadTimeout 設置為true時,核心線程也會超時回收
- maximumPoolSize(必需):最大線程數量,當線程池內的線程數量到達該數之后,后續的新任務將交由拒絕策略處理
- keepAliveTime(必需):線程閑置超時時長。如果閑置線程的時間超過該時長,非核心線程就會被回收,如果allowCoreThreadTimeout 設置為true時,核心線程也會超時回收
- unit(必需):keepAliveTime參數的時間單位
- workQueue(必需):線程等待隊列即任務等待的隊列
- threadFactory(可選):線程工廠,用于指定線程池創建新線程的方式
- handler(可選):拒絕策略,當到達最大線程數時需要執行的拒絕策略, 默認為AbortPolicy即丟棄任務并拋異常
提交任務的流程
線程池實現類——ThreadPoolExecutor
構造方法 | 參數說明 |
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) | corePoolSize:核心線程池大小 maximumPoolSize:最大線程池大小 keepAliveTime:當線程數>核心線程數時,這是 多余線程在任務執行完成后最大的存活時間 unit:時間單位 workQueue:線程等待隊列即任務等待的隊列 |
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) | corePoolSize:核心線程池大小 maximumPoolSize:最大線程池大小 keepAliveTime:當線程數>核心線程數時,這是 多余線程在任務執行完成后最大的存活時間 unit:時間單位 workQueue:線程等待隊列即任務等待的隊列 threadFactory:線程創建工廠 |
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) | corePoolSize:核心線程池大小 maximumPoolSize:最大線程池大小 keepAliveTime:當線程數>核心線程數時,這是 多余線程在任務執行完成后最大的存活時間 unit:時間單位 workQueue:線程等待隊列即任務等待的隊列 handler:拒絕執行某個線程的策略LinkedBlockingQueue |
LinkedBlockingQueue<Runnable> 隊列默認size=Integer.MAX_VALUE,即是一個無界隊列 底層實現是鏈表;讀和寫使用的是兩個不同的鎖,所以是讀寫分離的隊列。 | 阻塞操作: take();//當隊列中無元素時,阻塞等待 put();//當隊滿時阻塞等待 非阻塞操作: poll();//當隊列為null時,返回null offer();//堆滿時return false; |
功能線程池
Executors已經為我們封裝好了四種常見的功能線程池:
- 定長線程池(FixedThreadPool)
- 定時線程池(ScheduledThreadPool )
- 可緩存線程池(CachedThreadPool)
- 單線程化線程池(SingleThreadExecutor)
從結構圖中能看到四種線程池的真正實現類是ThreadPoolExecutor
線程池類型
1、newScheduledThreadPool 調度型線程池
- 支持定時及周期性的執行任務,提交任務時支持設置任務的調度周期
- 只限制了核心線程數,也就是最大線程數為Integer.MAX_VALUE,當添加任務的速度大于線程池處理任務的速度,可能會創建大量的線程,消耗資源,甚至導致OOM
1.1 構造
構造方法 | 參數 |
newScheduledThreadPool(int corePoolSize) | corePoolSize:corePoolSize maximumPoolSize:Integer.MAX_VALUE keepAliveTime:0 unit:NANOSECONDS workQueue:DelayedWorkQueue |
newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory) |
1.2 任務隊列-DelayedWorkQueue
- 該隊列的數據結構是優先級隊列(依賴堆實現),當新來任務時將該task插入堆并根據優先級重新調整堆,保證優先級最高的task在fist index
- 執行任務時,獲取fist index中的task,并保證等待夠delay時間后再執行(當fist task執行后也需要重新調整堆)
2、newCachedThreadPool 緩存型線程池
- 無核心線程數,無非核心線程數,執行完閑置60s回收,任務隊列為不存儲元素的阻塞隊列
- 適用于短期異步的小任務,或負載較輕的服務器
- 創建的最大線程數為Integer.MAX_VALUE,當添加任務的速度大于線程池處理任務的速度,可能會創建大量的線程,消耗資源,甚至導致OOM
2.1 構造方法
構造方法 | 參數 |
ExecutorService newCachedThreadPool() | 參數默認值 corePoolSize:0 maximumPoolSize:Integer.MAX_VALUE keepAliveTime:60L unit:TimeUnit.SECONDS workQueue:SynchronousQueue<Runnable> |
ExecutorService newCachedThreadPool(ThreadFactory threadFactory) |
2.2 任務隊列-SynchronousQueue
- 隊列是不存儲元素緩存隊列的,每次要進行offer操作時必須等待poll操作,否則不能繼續添加元素
- 當前線程A執行offer操作將task添加到queue中,若沒有另一個線程來消費該task,那線程A會一直阻塞直到另一個線程來消費該task
3、newFixedThreadPool
- 創建固定大小的線程池。每次提交一個任務就創建一個線程,直到線程達到線程池的最大大小。線程池的大小一旦達到最大值就會保持不變,如果某個線程因為執行異常而結束,那么線程池會補充一個新線程
- 適用于限制當前線程數量的應用場景,適用于負載比較重的服務器
- 創建了一個無界隊列LinkedBlockingQueuesize,是一個最大值為Integer.MAX_VALUE的線程阻塞隊列,當添加任務的速度大于線程池處理任務的速度,可能會在隊列堆積大量的請求,消耗很大的內存,甚至導致OOM
3.1 構造方法
構造方法 | 參數 |
ExecutorService newFixedThreadPool(int nThreads) | corePoolSize:nThreads maximumPoolSize:nThreads keepAliveTime:0L unit:TimeUnit.MILLISECONDS, workQueue:LinkedBlockingQueue<Runnable> threadFactory |
ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) |
3.2 任務隊列-LinkedBlockingQueue<Runnable>
- 隊列默認size=Integer.MAX_VALUE即是一個無界隊列,底層實現是鏈表,當添加任務的速度大于線程池處理任務的速度,可能會在隊列堆積大量的請求,消耗很大的內存,甚至導致OOM
- 讀和寫使用的是兩個不同的鎖,所以是讀寫分離的隊列
4、SingleThreadExecutor
- 創建一個單線程的線程池。這個線程池只有一個線程在工作,也就是相當于單線程串行執行所有任務,如果這個唯一的線程因為異常結束,那么會有一個新的線程來替代它
- 此線程池保證所有任務的執行順序按照任務的提交順序執行
4.1 構造方法
構造方法 | 參數 |
ExecutorService newSingleThreadExecutor() | corePoolSize:1 maximumPoolSize:1 keepAliveTime:0L unit:TimeUnit.MILLISECONDS, workQueue:LinkedBlockingQueue<Runnable> threadFactory |
ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) |
4.2 任務隊列-LinkedBlockingQueue<Runnable>
- 隊列默認size=Integer.MAX_VALUE即是一個無界隊列,底層實現是鏈表,當添加任務的速度大于線程池處理任務的速度,可能會在隊列堆積大量的請求,消耗很大的內存,甚至導致OOM
- 讀和寫使用的是兩個不同的鎖,所以是讀寫分離的隊列
線程池拒絕策略:
實現java.util.concurrent.RejectedExecutionHandler接口
1,CallerRunsPolicy:當想提交任務的線程池還存活,就由提交task的當前線程來執行
2,AbortPolicy:丟棄任務并拋出RejectedExecutionException異常,(默認拒絕策略)
3,DiscardPolicy:丟棄任務但是不拋異常
4,DiscardOldestPolicy:當想提交任務的線程池還存活,就將丟棄隊列最前面的任務,然后重新提交被拒絕的任務
對比
類型 | 池內線程數量 | 任務隊列 | 特點 | 應用場景 |
newScheduledThreadPool | 核心線程:固定 非核心線程:無限制 | DelayedWorkQueue |
| 執行定時/周期性任務 |
newCachedThreadPool | 無限制 | SynchronousQueue |
| 執行數量多,耗時少的線程任務 |
newFixedThreadPool | 固定 | LinkedBlockingQueue |
| 控制線程的最大并發數 |
newSingleThreadExecutor | 1個 | LinkedBlockingQueue |
| 單線程 |