執行緒池原理(JDK1.8)
Java中的執行緒池
ThreadPoolExecutor是執行緒池類。對於執行緒池,可以通俗的將它理解為”存放一定數量執行緒的一個執行緒集合。執行緒池允許若個執行緒同時允許,允許同時執行的執行緒數量就是執行緒池的容量;當新增的到執行緒池中的執行緒超過它的容量時,會有一部分執行緒阻塞等待。執行緒池會通過相應的排程策略和拒絕策略,對新增到執行緒池中的執行緒進行管理。
組成(這部分轉自執行緒池原理——skywang12345)
// 阻塞佇列
private final BlockingQueue<Runnable> workQueue;
// 互斥鎖
private final ReentrantLock mainLock = new ReentrantLock();
// 執行緒集合。一個Worker對應一個執行緒。
private final HashSet<Worker> workers = new HashSet<Worker>();
// “終止條件”,與“mainLock”繫結。
private final Condition termination = mainLock.newCondition();
// 執行緒池中執行緒數量曾經達到過的最大值。
private int largestPoolSize;
// 已完成任務數量
private long completedTaskCount;
// ThreadFactory物件,用於建立執行緒。
private volatile ThreadFactory threadFactory;
// 拒絕策略的處理控制程式碼。
private volatile RejectedExecutionHandler handler;
// 保持執行緒存活時間。
private volatile long keepAliveTime;
private volatile boolean allowCoreThreadTimeOut;
// 核心池大小
private volatile int corePoolSize;
// 最大池大小
private volatile int maximumPoolSize;
1.workers
workers是HashSet型別,即它是一個Worker集合。而一個Worker對應一個執行緒,也就是說執行緒池通過workers包含了”一個執行緒集合”。當Worker對應的執行緒池啟動時,它會執行執行緒池中的任務;當執行完一個任務後,它會從執行緒池的阻塞佇列中取出一個阻塞的任務來繼續執行。
wokers的作用是,執行緒池通過它實現了”允許多個執行緒同時執行”。
2.workQueue
workQueue是BlockingQueue型別,即它是一個阻塞佇列。當執行緒池中的執行緒數超過它的容量的時候,執行緒會進入阻塞佇列進行阻塞等待。
通過workQueue,執行緒池實現了阻塞功能。
3. mainLock
mainLock是互斥鎖,通過mainLock實現了對執行緒池的互斥訪問。
4. corePoolSize和maximumPoolSize
corePoolSize是”核心池大小”,maximumPoolSize是”最大池大小”。它們的作用是調整”執行緒池中實際執行的執行緒的數量”。
例如,當新任務提交給執行緒池時(通過execute方法)。
– 如果此時,執行緒池中執行的執行緒數量< corePoolSize,則建立新執行緒來處理請求。
– 如果此時,執行緒池中執行的執行緒數量> corePoolSize,但是卻< maximumPoolSize;則僅當阻塞佇列滿時才建立新執行緒。
如果設定的 corePoolSize 和 maximumPoolSize 相同,則建立了固定大小的執行緒池。如果將 maximumPoolSize 設定為基本的無界值(如 Integer.MAX_VALUE),則允許池適應任意數量的併發任務。在大多數情況下,核心池大小和最大池大小的值是在建立執行緒池設定的;但是,也可以使用 setCorePoolSize(int) 和 setMaximumPoolSize(int) 進行動態更改。
5. poolSize
poolSize是當前執行緒池的實際大小,即執行緒池中任務的數量。
6. allowCoreThreadTimeOut和keepAliveTime
allowCoreThreadTimeOut表示是否允許”執行緒在空閒狀態時,仍然能夠存活”;而keepAliveTime是當執行緒池處於空閒狀態的時候,超過keepAliveTime時間之後,空閒的執行緒會被終止。
7. threadFactory
threadFactory是ThreadFactory物件。它是一個執行緒工廠類,”執行緒池通過ThreadFactory建立執行緒”。
8. handler
handler是RejectedExecutionHandler型別。它是”執行緒池拒絕策略”的控制程式碼,也就是說”當某任務新增到執行緒池中,而執行緒池拒絕該任務時,執行緒池會通過handler進行相應的處理”。
原理(原始碼是JDK1.8)
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
/*
1、判斷當前的工作執行緒是否小於執行緒池裡的核心執行緒,如果滿足,則建立一個新的工作執行緒來執行任務。
如果不滿足,則進入下個流程。
注意:此時addWorker的第二個引數為true;
*/
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
/*
2、執行緒池判斷工作佇列是否已滿,如果工作佇列沒有滿,則將新提交的任務儲存在這個工作佇列裡。
如果工作佇列滿了,則進入下個流程。
*/
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//3、嘗試建立執行緒 注意:此時addWorker的第二個引數為false,下面會解釋
else if (!addWorker(command, false))
reject(command);
}
//該方法用於建立執行緒,注意該方法的第二個引數core
private boolean addWorker(Runnable firstTask, boolean core) {
retry:
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
// Check if queue empty only if necessary.
if (rs >= SHUTDOWN &&
! (rs == SHUTDOWN &&
firstTask == null &&
! workQueue.isEmpty()))
return false;
for (;;) {
int wc = workerCountOf(c);
/*
當core為false時,下面判斷執行緒池corePoolSize和maximumPoolSize 的差值,如果此時,
執行緒池中執行的執行緒數量> corePoolSize,但是卻< maximumPoolSize,則會繼續建立一個
新的工作執行緒。
*/
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
// else CAS failed due to workerCount change; retry inner loop
}
}
boolean workerStarted = false;
boolean workerAdded = false;
Worker w = null;
try {
w = new Worker(firstTask);
final Thread t = w.thread;
if (t != null) {
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
// Recheck while holding lock.
// Back out on ThreadFactory failure or if
// shut down before lock acquired.
int rs = runStateOf(ctl.get());
if (rs < SHUTDOWN ||
(rs == SHUTDOWN && firstTask == null)) {
if (t.isAlive()) // precheck that t is startable
throw new IllegalThreadStateException();
workers.add(w);
int s = workers.size();
if (s > largestPoolSize)
largestPoolSize = s;
workerAdded = true;
}
} finally {
mainLock.unlock();
}
if (workerAdded) {
t.start();
workerStarted = true;
}
}
} finally {
if (! workerStarted)
addWorkerFailed(w);
}
return workerStarted;
}
總結
1、判斷當前的工作執行緒是否小於執行緒池裡的核心執行緒,如果滿足,則建立一個新的工作執行緒來執行任務。不滿足則進入下個流程。
2、執行緒池判斷工作佇列是否已滿,如果工作佇列沒有滿,則將新提交的任務儲存在這個工作佇列裡。如果工作佇列滿了,則進入下個流程。
3、判斷執行緒池corePoolSize和maximumPoolSize 的差值,如果此時,執行緒池中執行的執行緒數量> corePoolSize,但是卻< maximumPoolSize,則建立一個新的工作執行緒來執行任務。如果已經滿了,則交給飽和策略來處理這個任務。
相關文章
- Java執行緒池二:執行緒池原理Java執行緒
- 執行緒池原理初探執行緒
- jdk1.8 執行緒池部分原始碼分析JDK執行緒原始碼
- SpringBoot執行緒池和Java執行緒池的實現原理Spring Boot執行緒Java
- java多執行緒:執行緒池原理、阻塞佇列Java執行緒佇列
- Java執行緒池核心原理剖析Java執行緒
- 執行緒池ThreadPoolExecutor實現原理執行緒thread
- 執行緒池核心原理淺析執行緒
- 圖解Java執行緒池原理圖解Java執行緒
- Java執行緒池原理及分析Java執行緒
- 深入學習執行緒池原理執行緒
- 執行緒池的實現原理執行緒
- 執行緒池原理與實踐執行緒
- 手寫執行緒池,對照學習ThreadPoolExecutor執行緒池實現原理!執行緒thread
- Java執行緒池的使用和原理Java執行緒
- JAVA執行緒池的原理及使用Java執行緒
- Java執行緒池原始碼及原理Java執行緒原始碼
- 執行緒和執行緒池執行緒
- 執行緒 執行緒池 Task執行緒
- 多執行緒【執行緒池】執行緒
- 手寫一個執行緒池,帶你學習ThreadPoolExecutor執行緒池實現原理執行緒thread
- 從原始碼的角度解析執行緒池執行原理原始碼執行緒
- Java面試必問之執行緒池的建立使用、執行緒池的核心引數、執行緒池的底層工作原理Java面試執行緒
- 執行緒池執行緒
- 深入Java原始碼理解執行緒池原理Java原始碼執行緒
- 深入理解執行緒池原理篇執行緒
- 執行緒池續:你必須要知道的執行緒池submit()實現原理之FutureTask!執行緒MIT
- 執行緒池以及四種常見執行緒池執行緒
- java執行緒池趣味事:這不是執行緒池Java執行緒
- java--執行緒池--建立執行緒池的幾種方式與執行緒池操作詳解Java執行緒
- 二. 執行緒管理之執行緒池執行緒
- Android多執行緒之執行緒池Android執行緒
- kuangshenshuo-多執行緒-執行緒池執行緒
- 多執行緒之手撕執行緒池執行緒
- java多執行緒9:執行緒池Java執行緒
- 執行緒池管理(1)-為什麼需要執行緒池執行緒
- Java執行緒池ThreadPoolExecutor實現原理剖析 #28Java執行緒thread
- Android執行緒池Android執行緒