目錄
0 框架類圖
常用的Executors類是工具類,靜態工廠方法(簡單工廠模式),實際生產ThreadPoolExecutor。
ThreadPoolExecutor是核心實現類,下面來詳細介紹
1. Executors工具類
API如下,常用幾種種靜態工廠方法newFixedThreadPool固定大小、newSingleThreadExecutor單線程、newCachedThreadPool、newScheduledThreadPool固定時延(定時任務),實際生產出來的都是ThreadPoolExecutor
ThreadPoolExecutor 構造參數 |
newFixedThreadPool(n) | newSingleThreadExecutor() | newCachedThreadPool() | newScheduledThreadPool(n) |
---|---|---|---|---|
corePoolSize | n(方法參數) | 1 | 0 | n |
maximumPoolSize | n | 1 | Integer.MAX_VALUE | Integer.MAX_VALUE |
keepAliveTime | 0 | 0 | 60 | 0 |
unit | MILLISECONDS毫秒 | MILLISECONDS毫秒 | SECONDS秒 | MILLISECONDS毫秒 |
workQueue | LinkedBlockingQueue | LinkedBlockingQueue | SynchronousQueue | DelayedWorkQueue |
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
...
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue());
}
2 ThreadPoolExecutor
2.1 API常用方法
2.1.1 構造方法
有4個構造方法,最常用第一個,帶5個參數,參數接受稍後詳解,
剩餘的就是多指明線程工廠和拒絕策略,線程工廠用與創建線程,而拒絕策略就是在提交任務數 > maxPoolSize+queueSize時拒絕線程。
第一個構造方法如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue);
ThreadPoolExecutor 是Executor的基本實現,構造參數如下,通過這些參數可以控制其大小等
參數 | 含義 | 圖解 |
---|---|---|
corePoolSize | 線程池基本大小 | |
maximumPoolSize | 線程池最大大小 | |
keepAliveTime |
線程存活時間, 空間時間**>keepAliveTime 標記爲可回收 |
|
unit |
時間單位, 枚舉可設置爲秒、毫秒等 |
|
workQueue | 工作隊列類型 |
2.1.2 核心方法execute(Runnable r)
提交任務到線程池
2.1.3 addWorker創建工作線程
前置會判斷當前的線程數量,此處省略了,當符合size條件符合(如上圖展示),就會
new Worker實例(會使用線程工廠threadFactory創建一個以當前worker爲Runnable參數的新線程),
然後一些狀態判斷,並加入到線程池ThreadPoolExecutor的workers集合,
最後啓動線程start,調度後就能執行這個Worker的run方法。具體請見下面Worker章節~
2.2 組件解析
主要包含Worker、ThreadFactory、BlockingQueue
2.2.1 worker
就是工作線程,實現了Runnable,並持有Runnable
構造方法
Worker(Runnable firstTask) {
setState(-1); // inhibit interrupts until runWorker
this.firstTask = firstTask;
this.thread = getThreadFactory().newThread(this);
}
run方法
主要是在while循環體中一直從任務隊列中獲取Runnable任務,直接調用其run方法,所以並不是提交多少次就會生產多少線程去執行任務的,工作線程是複用的,工作線程的run方法中循環調用任務的run方法而已。(命令模式)
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask;
w.firstTask = null;
w.unlock(); // 允許中斷
boolean completedAbruptly = true;
try {
while (task != null || (task = getTask()) != null) { // 首次任務||從隊列獲取任務workQueue.take();
w.lock();
// 如果線程池被置爲stoping,中斷線程 否則保證不中斷
if ((runStateAtLeast(ctl.get(), STOP) ||
(Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) &&
!wt.isInterrupted())
wt.interrupt();
try {
beforeExecute(wt, task);// 空實現
try {
task.run(); // 執行任務!!!
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown);// 空實現
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
}
completedAbruptly = false;
} finally {
processWorkerExit(w, completedAbruptly); // 空閒且非core則銷燬worker
}
}
2.2.2 ThreadFactory
ThreadFactory是個接口,顧名思義就是用於生產線程的工廠,(簡單工廠模式),我們通常不指定這個參數,所以會選用默認的實現。
默認實現DefaultThreadFactory是Executors的靜態內部類,主要生產線程的方法非常簡單,如下
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(),0);
if (t.isDaemon())
t.setDaemon(false); //非守護線程
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY); //普通優先級
return t;
}
2.2.3 BlockingQueue
通常的生產者/消費者模型會選擇使用BlockingQueue,主要特性就是在空時取會阻塞,滿時offer會阻塞,家族如下,