1. 程式人生 > 其它 >Java基礎回顧:ThreadPoolExecutor

Java基礎回顧:ThreadPoolExecutor

個人筆記,網上資料加原始碼整理,侵刪 1. 主要引數
int corePoolSize
核心執行緒數

int maximumPoolSize
最大執行緒數

long keepAliveTime
執行緒等待時間

TimeUnit unit
時間單位

BlockingQueue<Runnable> workQueue
阻塞佇列

ThreadFactory threadFactory
執行緒工廠,用來建立執行緒

RejectedExecutionHandler handler
拒絕策略
2. 執行流程 3. 執行機制 1)執行緒池如何維護自身狀態 執行緒池內部維護兩個值:執行狀態(runState)和執行緒數量(workerCount),用一個AtomicInteger,高三位儲存執行狀態,低29位儲存執行緒數量。 內部封裝的獲取生命週期狀態和執行緒池數量的方法:
private static int runStateOf(int c)     { return c & ~CAPACITY; }
private static int workerCountOf(int c)  { return c & CAPACITY; }
private static int ctlOf(int rs, int wc) { return rs | wc; }
ThreadPoolExecutor執行狀態分為五種:RUNNINGSHUTDOWNSTOPTIDYINGTERMINATED 生命週期轉換如下: 2)執行緒池如何管理任務 執行緒池執行核心機制 所有任務的排程都是有execute方法完成的,這部分完成的工作是:檢查當前執行緒池的執行狀態、工作執行緒數、執行策略,決定接下來的執行流程,是直接申請執行緒執行,或是緩衝到佇列中等待執行,亦或是直接拒絕執行該任務。 執行過程如下:
  • 檢查執行緒池執行狀態,如果不是RUNNING狀態,則直接拒絕執行任務
  • 如果workerCount < corePoolSize,則直接建立一個執行緒並執行任務
  • 如果workerCount >= corePoolSize,但是阻塞佇列沒滿,將任務放入阻塞佇列等待執行
  • 如果workerCount >= corePoolSize && workerCount < maximumPoolSize,且阻塞佇列已滿,建立一個新執行緒執行任務
  • 如果workerCount > maximumPoolSize,並且阻塞佇列已滿,則根據拒絕策略來處理該任務,預設處理方式是直接丟擲異常
拒絕策略 3)執行緒池如何管理執行緒 執行緒池為了掌握執行緒的狀態並維護執行緒的生命週期,設計了執行緒池內的工作執行緒Worker Worker執行緒執行任務模型: Worker通過繼承AQS
(AbstractQueuedSynchronizer),使用AQS來實現獨佔鎖這個功能 AQS使用一個int成員變數state來表示同步狀態,如ReentrantLock的lock方法,實際上就是通過compareAndSetState(0, 1)方法使state值0加到1,維護state值來獲取鎖和釋放鎖。通過內建的FIFO佇列來完成獲取資源執行緒的排隊工作(公平鎖)。AQS使用CAS對該同步狀態進行原子操作實現對其值的修改。 執行緒池中執行緒的銷燬依賴JVM自動回收,執行緒池做的工作是根據當前執行緒池的狀態維護一定數量的執行緒引用,防止這部分執行緒被JVM回收。 Worker被創建出來後,就會不斷的進行輪詢,然後獲取任務去執行,核心執行緒可以無限等待獲取任務,非核心執行緒要限時獲取任務。當Worker無法獲取到任務,也就是獲取的任務為空時,迴圈會結束,Worker會主動消除自身線上程池內的應用 Worker執行緒執行任務流程 4)執行緒池鎖機制 AQS,lock,unlock 非重入鎖
public void lock()        { acquire(1); }
public boolean tryLock()  { return tryAcquire(1); }
public void unlock()      { release(1); }
public boolean isLocked() { return isHeldExclusively(); }
可重入鎖(ReentrantLock)
  • 公平鎖 FIFO,先到先得原則
  • 非公平鎖
重進入是指任意執行緒在獲取到鎖之後能夠再次獲取該鎖而不會被鎖所阻塞
public int getPoolSize() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        // Remove rare and surprising possibility of
        // isTerminated() && getPoolSize() > 0
        return runStateAtLeast(ctl.get(), TIDYING) ? 0
            : workers.size();
    } finally {
        mainLock.unlock();
    }
}
4. 主要業務場景 後臺資料匯出任務 快速響應使用者請求 快速處理批量任務 一點浩然氣,千里快哉風!