執行緒池詳解

2021-09-21 07:17:25 字數 4707 閱讀 3891

**:

執行緒的優點:

1、執行緒的無限制建立需要占用記憶體資源、消耗時間。而使用執行緒池可以減少建立和銷毀執行緒的次數,每個工作執行緒都可以重複使用。

2、可以根據系統的承受能力,調整執行緒池中工作執行緒的數量,防止因為消耗過多記憶體導致伺服器崩潰。

執行緒池的構造方法:

public threadpoolexecutor(int corepoolsize,int maximumpoolsize,long keepalivetime,timeunit unit, blockingqueueworkqueue ,threadfactory threadfactory,rejectedexecutionhandler handler);
corepoolsize:核心池的大小

maximumpoolsize:執行緒池最大執行緒數

keepalivetime:表示執行緒沒有任務執行時最多保持多久時間會終止

unit:引數keepalivetime的時間單位,有7種取值(天、小時、分鐘、秒、毫秒、微秒、納秒)

workqueue:乙個阻塞佇列,用來儲存等待執行的任務

threadfactory:執行緒工廠,主要用來建立執行緒

handler:表示當拒絕處理任務時的策略,有以下四種取值

threadpoolexecutor.abortpolicy:丟棄任務並丟擲rejectedexecutionexception異常。

threadpoolexecutor.discardpolicy:也是丟棄任務,但是不丟擲異常。

threadpoolexecutor.discardoldestpolicy:丟棄佇列最前面的任務,然後重新嘗試執行任務(重複此過程)

threadpoolexecutor.callerrunspolicy:由呼叫執行緒處理該任務

corepoolsize在很多地方被翻譯成核心池大小,其實我的理解這個就是執行緒池的大小。

舉個簡單的例子:

假如有乙個工廠,工廠裡面有10個工人,每個工人同時只能做一件任務。

因此只要當10個工人中有工人是空閒的,來了任務就分配給空閒的工人做;

當10個工人都有任務在做時,如果還來了任務,就把任務進行排隊等待;

如果說新任務數目增長的速度遠遠大於工人做任務的速度,那麼此時工廠主管可能會想補救措施,比如重新招4個臨時工人進來;

然後就將任務也分配給這4個臨時工人做;

如果說著14個工人做任務的速度還是不夠,此時工廠主管可能就要考慮不再接收新的任務或者拋棄前面的一些任務了。

當這14個工人當中有人空閒時,而新任務增長的速度又比較緩慢,工廠主管可能就考慮辭掉4個臨時工了,只保持原來的10個工人,畢竟請額外的工人是要花錢的。

這個例子中的corepoolsize就是10,而maximumpoolsize就是14(10+4)。

也就是說corepoolsize就是執行緒池大小,maximumpoolsize在我看來是執行緒池的一種補救措施,即任務量突然過大時的一種補救措施。

如果當前執行緒池中的執行緒數目小於corepoolsize,則每來乙個任務,就會建立乙個執行緒去執行這個任務;

如果當前執行緒池中的執行緒數目》=corepoolsize,則每來乙個任務,會嘗試將其新增到任務快取佇列當中,若新增成功,則該任務會等待空閒執行緒將其取出去執行;若新增失敗(一般來說是任務快取佇列已滿),則會嘗試建立新的執行緒去執行這個任務;

如果當前執行緒池中的執行緒數目達到maximumpoolsize,則會採取任務拒絕策略進行處理;

如果執行緒池中的執行緒數量大於 corepoolsize時,如果某執行緒空閒時間超過keepalivetime,執行緒將被終止,直至執行緒池中的執行緒數目不大於corepoolsize;如果允許為核心池中的執行緒設定存活時間,那麼核心池中的執行緒空閒時間超過keepalivetime,執行緒也會被終止。

1.執行緒池狀態

在threadpoolexecutor中定義了乙個volatile變數,另外定義了幾個static final變數表示執行緒池的各個狀態:

volatile int runstate;

static final int running = 0;

static final int shutdown = 1;

static final int stop = 2;

static final int terminated = 3;

runstate表示當前執行緒池的狀態,它是乙個volatile變數用來保證執行緒之間的可見性;

下面的幾個static final變數表示runstate可能的幾個取值。

當建立執行緒池後,初始時,執行緒池處於running狀態;

如果呼叫了shutdown()方法,則執行緒池處於shutdown狀態,此時執行緒池不能夠接受新的任務,它會等待所有任務執行完畢;

如果呼叫了shutdownnow()方法,則執行緒池處於stop狀態,此時執行緒池不能接受新的任務,並且會去嘗試終止正在執行的任務;

當執行緒池處於shutdown或stop狀態,並且所有工作執行緒已經銷毀,任務快取佇列已經清空或執行結束後,執行緒池被設定為terminated狀態。

3.執行緒池中的執行緒初始化

預設情況下,建立執行緒池之後,執行緒池中是沒有執行緒的,需要提交任務之後才會建立執行緒。

在實際中如果需要執行緒池建立之後立即建立執行緒,可以通過以下兩個方法辦到:

prestartcorethread():初始化乙個核心執行緒;

prestartallcorethreads():初始化所有核心執行緒

下面是這2個方法的實現:

public boolean prestartcorethread() 

public int prestartallcorethreads()

注意上面傳進去的引數是null,根據第2小節的分析可知如果傳進去的引數為null,則最後執行執行緒會阻塞在gettask方法中的 1 r = workqueue.take();

即等待任務佇列中有任務。

4.任務快取佇列及排隊策略

在前面我們多次提到了任務快取佇列,即workqueue,它用來存放等待執行的任務。

workqueue的型別為blockingqueue,是執行緒安全的通常可以取下面五種型別:

1)arrayblockingqueue:基於陣列的先進先出佇列,此佇列建立時必須指定大小;這個是可以指定公平性的,如果是true,就是先進先出,如果是false,順序就不確定。不允許null

2)linkedblockingqueue:基於鍊錶的先進先出佇列,如果建立時沒有指定此佇列大小,則預設為integer.max_value;這個一般用於fixedthreadpool和singlethreadexecutor()

3)synchronousqueue:這個佇列比較特殊,它不會儲存提交的任務,而是將直接新建乙個執行緒來執行新來的任務。這個一般用於cachetheadpool。

4)priorityblockingqueue:類似於linkedblockqueue,但其所含物件的排序不是fifo,而是依據物件的自然排序順序或者是建構函式的comparator決定的順序.。不允許null

5)delayqueue:是乙個無界的blockingqueue,用於放置實現了delayed介面的物件,其中的物件只能在其到期時才能從佇列中取走。這種佇列是有序的,即隊頭物件的延遲到期時間最長。注意:不能將null元素放置到這種佇列中。scheduledthreadpool()用這個。

5.任務拒絕策略

當執行緒池的任務快取佇列已滿並且執行緒池中的執行緒數目達到maximumpoolsize,如果還有任務到來就會採取任務拒絕策略,通常有以下四種策略:

threadpoolexecutor.abortpolicy:丟棄任務並丟擲rejectedexecutionexception異常。

threadpoolexecutor.discardpolicy:也是丟棄任務,但是不丟擲異常。

threadpoolexecutor.discardoldestpolicy:丟棄佇列最前面的任務,然後重新嘗試執行任務(重複此過程)

threadpoolexecutor.callerrunspolicy:由呼叫執行緒處理該任務

6.執行緒池的關閉

threadpoolexecutor提供了兩個方法,用於執行緒池的關閉,分別是shutdown()和shutdownnow(),其中:

shutdown():不會立即終止執行緒池,而是要等所有任務快取佇列中的任務都執行完後才終止,但再也不會接受新的任務

shutdownnow():立即終止執行緒池,並嘗試打斷正在執行的任務,並且清空任務快取佇列,返回尚未執行的任務

7.執行緒池容量的動態調整

threadpoolexecutor提供了動態調整執行緒池容量大小的方法:setcorepoolsize()和setmaximumpoolsize(),

setcorepoolsize:設定核心池大小

setmaximumpoolsize:設定執行緒池最大能建立的執行緒數目大小

當上述引數從小變大時,threadpoolexecutor進行執行緒賦值,還可能立即建立新的執行緒來執行任務。

執行緒池詳解

1.執行緒池的幾個重要的引數?public threadpoolexecutor intcorepoolsize,intmaximumpoolsize,long keepalivetime,timeunit unit,blockingqueueworkqueue,rejectedexecutionh...

jdk執行緒池詳解

public threadpoolexecutor int corepoolsize,核心執行緒數 intmaximumpoolsize,最大執行緒數 long keepalivetime,空閒時間 timeunit unit,時間單位 blockingqueueworkqueue,等待佇列 thr...

Android執行緒池詳解

最近在看okhttp的原始碼,看著看著就看到了有執行緒池的地方,以前自己對這個東西就也就感到雲裡霧裡的,所以 想把執行緒池的知識點和原始碼完整的看一篇 1.執行緒池有什麼用?a.重用執行緒池中存在的執行緒,避免因為執行緒的大量建立和銷毀所帶來的效能開銷 完成一項任務的時間t 建立線 2.thread...