執行緒池ThreadPoolExecutor實現原理

2021-10-08 02:13:55 字數 4047 閱讀 4803

執行緒是乙個程式設計師一定會涉及到的乙個概念,但是執行緒的建立和切換都是代價比較大的。所以,我們有沒有乙個好的方案能做到執行緒的復用呢?這就涉及到乙個概念——執行緒池。合理的使用執行緒池能夠帶來3個很明顯的好處:

1.降低資源消耗:通過重用已經建立的執行緒來降低執行緒建立和銷毀的消耗

2.提高響應速度:任務到達時不需要等待執行緒建立就可以立即執行。

3.提高執行緒的可管理性:執行緒池可以統一管理、分配、調優和監控。

threadpoolexecutor的構造方法

public

threadpoolexecutor

(int corepoolsize,

int maximumpoolsize,

long keepalivetime,

timeunit unit,

blockingqueue

workqueue,

threadfactory threadfactory,

rejectedexecutionhandler handler)

corepoolsize:執行緒池中的核心執行緒數;

keepalivetime:執行緒池中非核心執行緒閒置超時時長(沒有任務執行時的**時間);

乙個非核心執行緒,如果閒置狀態的時長超過這個引數所設定的時長,就會被銷毀掉

timeunit:時間單位。可選的單位有分鐘(minutes),秒(seconds),毫秒(milliseconds) 等;

workqueue:任務的阻塞佇列,快取將要執行的runnable任務,由各執行緒輪詢該任務佇列獲取任務執行。可以選擇以下幾個阻塞佇列。

arrayblockingqueue:是乙個基於陣列結構的有界阻塞佇列,此佇列按 fifo(先進先出)原則對元素進行排序。

linkedblockingqueue:乙個基於鍊錶結構的阻塞佇列,此佇列按fifo (先進先出) 排序元素,吞吐量通常要高於arrayblockingqueue。靜態工廠方法executors.newfixedthreadpool()使用了這個佇列。

synchronousqueue:乙個不儲存元素的阻塞佇列。每個插入操作必須等到另乙個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態,吞吐量通常要高於linkedblockingqueue,靜態工廠方法executors.newcachedthreadpool使用了這個佇列。

priorityblockingqueue:乙個具有優先順序的無限阻塞佇列。

threadfactory:執行緒建立的工廠。可以進行一些屬性設定,比如執行緒名,優先順序等等,有預設實現。

rejectedexecutionhandler:任務拒絕策略,當執行執行緒數已達到maximumpoolsize,佇列也已經裝滿時會呼叫該引數拒絕任務,預設情況下是abortpolicy,表示無法處理新任務時丟擲異常。以下是jdk1.5提供的四種策略。

abortpolicy:直接丟擲異常。

discardoldestpolicy:丟棄佇列裡最老的乙個任務,並執行當前任務。

discardpolicy:不處理,丟棄掉。

threadpoolexecutor的狀態變數

private

final atomicinteger ctl =

newatomicinteger

(ctlof

(running,0)

);private

static

final

int count_bits = integer.size -3;

private

static

final

int capacity =(1

<< count_bits)-1

;// runstate is stored in the high-order bits

//count_bits=29 左移29位

//1 = 0000 0000 0000 0000 0000 0000 0000 0001

//-1 = 1111 1111 1111 1111 1111 1111 1111 1111

// running = 111000 0000 0000 0000 0000 0000 0000 0000

private

static

final

int running =-1

<< count_bits;

//shutdown = 000

private

static

final

int shutdown =

0<< count_bits;

//stop = 001

private

static

final

int stop =

1<< count_bits;

//tidying =010

private

static

final

int tidying =

2<< count_bits;

//terminated = 011

private

static

final

int terminated =

3<< count_bits;

其中ctl是threadpoolexecutor的同步狀態變數。

workercountof()方法取得當前執行緒池的執行緒數量,演算法是將ctl的值取低29位。

runstateof()方法取得執行緒池的狀態,演算法是將ctl的值取高3位:

running 111 表示正在執行

shutdown 000 表示拒絕接收新的任務

stop 001 表示拒絕接收新的任務並且不再處理任務佇列中剩餘的任務,並且中斷正在執行的任務。

tidying 010 表示所有執行緒已停止,準備執行terminated()方法。

terminated 011 表示已執行完terminated()方法。

execute()方法
public

void

execute

(runnable command)

//2.判斷執行緒池的狀態,如果是running狀態,並且阻塞佇列workqueue未滿if(

isrunning

(c)&& workqueue.

offer

(command)

)//通過addworke建立乙個執行緒,並將任務新增到該執行緒,然後啟動。如果addworker執行失敗,執行拒絕策略

elseif(

!addworker

(command,

false))

reject

(command)

;}

以上**對應了三種情況:

addwork()方法

執行緒池是維護了一批執行緒來處理使用者提交的任務,達到執行緒復用的目的,執行緒池維護的這批執行緒被封裝成了worker。

private

boolean

addworker

(runnable firsttask,

boolean core)

}//這裡已經成功執行了cas操作將執行緒池數量+1,下面建立執行緒

boolean workerstarted =

false

;boolean workeradded =

false

; worker w = null;

try}

finally

if(workeradded)}}

finally

return workerstarted;

}

執行緒 執行緒池

執行緒池是一種多執行緒處理形式,處理過程中將任務新增到佇列,然後在建立執行緒後執行,主要實現 建立執行緒和管理執行緒,並且給執行緒分配任務。執行緒池中的執行緒是併發執行的。乙個比較簡單的執行緒池至少應包含執行緒池管理器 工作執行緒 任務列隊 任務介面等部分。其中執行緒池管理器的作用是建立 銷毀並管理...

執行緒 執行緒池

乙個簡單執行緒的建立和銷毀如下 與程序程序相比,執行緒是一種輕量級的工具,但是輕量並不代表沒有,它的建立和關閉依然需要花費時間,如果建立和銷毀的時間還大於執行緒本身完成的工作,那就會得不償失,甚至會造成out of memory。即使沒有,大量的執行緒 也會給gc帶來巨大的壓力。為了解決這樣的問題,...

mysql 執行緒池 c MySQL執行緒池

mysql執行緒池 在麼mysql中,執行緒池指的是用來管理處理mysql客戶端連線任務的執行緒的一種機制。如果把執行緒看做系統資源那麼執行緒池本質上是對系統資源的管理,對應作業系統來說執行緒的建立和銷毀是比較消耗系統資源的,頻繁的建立與銷毀執行緒必然給系統帶來不必要的資源浪費,特別是在高負載的情況...