執行緒池使用

2021-10-06 13:57:32 字數 2875 閱讀 4215

一、執行緒池的構造器:

public threadpoolexecutor(int corepoolsize,

int maximumpoolsize,

long keepalivetime,

timeunit unit,

blockingqueueworkqueue,

threadfactory threadfactory,

rejectedexecutionhandler handler)

二、android中四種常見執行緒池

①newsinglethreadexecutor

單個執行緒的執行緒池,即執行緒池中每次只有乙個執行緒工作,單執行緒序列執行任務

②newfixedthreadexecutor(n)

固定數量的執行緒池,每提交乙個任務就是乙個執行緒,直到達到執行緒池的最大數量,然後後面進入等待佇列直到前面的任務完成才繼續執行

③newcachethreadexecutor(推薦使用)

可快取執行緒池,當執行緒池大小超過了處理任務所需的執行緒,那麼就會**部分空閒(一般是60秒無執行)的執行緒,當有任務來時,又智慧型的新增新執行緒來執行。

④newschedulethreadexecutor

大小無限制的執行緒池,支援定時和週期性的執行執行緒

三、blockingqueue的選擇。

例子一:使用直接提交策略,也即synchronousqueue。

首先synchronousqueue是無界的,也就是說他存數任務的能力是沒有限制的,但是由於該queue本身的特性,在某次新增元素後必須等待其他執行緒取走後才能繼續新增。在這裡不是核心執行緒便是新建立的執行緒,但是我們試想一樣下,下面的場景。

我們使用一下引數構造threadpoolexecutor:

new threadpoolexecutor(

2, 3, 30, timeunit.seconds,

new synchronousqueue(),

new recorderthreadfactory("cookierecorderpool"),

new threadpoolexecutor.callerrunspolicy());

當核心執行緒已經有2個正在執行.

此時繼續來了乙個任務(a),根據前面介紹的「如果執行的執行緒等於或多於 corepoolsize,則executor始終首選將請求加入佇列,而不新增新的執行緒。」,所以a被新增到queue中。

又來了乙個任務(b),且核心2個執行緒還沒有忙完,ok,接下來首先嘗試1中描述,但是由於使用的synchronousqueue,所以一定無法加入進去。

此時便滿足了上面提到的「如果無法將請求加入佇列,則建立新的執行緒,除非建立此執行緒超出maximumpoolsize,在這種情況下,任務將被拒絕。」,所以必然會新建乙個執行緒來執行這個任務。

暫時還可以,但是如果這三個任務都還沒完成,連續來了兩個任務,第乙個新增入queue中,後乙個呢?queue中無法插入,而執行緒數達到了maximumpoolsize,所以只好執行異常策略了。

所以在使用synchronousqueue通常要求maximumpoolsize是無界的,這樣就可以避免上述情況發生(如果希望限制就直接使用有界佇列)。對於使用synchronousqueue的作用jdk中寫的很清楚:此策略可以避免在處理可能具有內部依賴性的請求集時出現鎖。

什麼意思?如果你的任務a1,a2有內部關聯,a1需要先執行,那麼先提交a1,再提交a2,當使用synchronousqueue我們可以保證,a1必定先被執行,在a1麼有被執行前,a2不可能新增入queue中。

例子二:使用無界佇列策略,即linkedblockingqueue

這個就拿newfixedthreadpool來說,根據前文提到的規則:

如果執行的執行緒少於 corepoolsize,則 executor 始終首選新增新的執行緒,而不進行排隊。那麼當任務繼續增加,會發生什麼呢?

如果執行的執行緒等於或多於 corepoolsize,則 executor 始終首選將請求加入佇列,而不新增新的執行緒。ok,此時任務變加入佇列之中了,那什麼時候才會新增新執行緒呢?

如果無法將請求加入佇列,則建立新的執行緒,除非建立此執行緒超出 maximumpoolsize,在這種情況下,任務將被拒絕。這裡就很有意思了,可能會出現無法加入佇列嗎?不像synchronousqueue那樣有其自身的特點,對於無界佇列來說,總是可以加入的(資源耗盡,當然另當別論)。換句說,永遠也不會觸發產生新的執行緒!corepoolsize大小的執行緒數會一直執行,忙完當前的,就從佇列中拿任務開始執行。所以要防止任務瘋長,比如任務執行的實行比較長,而新增任務的速度遠遠超過處理任務的時間,而且還不斷增加,不一會兒就爆了。

例子三:有界佇列,使用arrayblockingqueue。

這個是最為複雜的使用,所以jdk不推薦使用也有些道理。與上面的相比,最大的特點便是可以防止資源耗盡的情況發生。

舉例來說,請看如下構造方法:

new threadpoolexecutor(

2, 4, 30, timeunit.seconds,

new arrayblockingqueue(2),

new recorderthreadfactory("cookierecorderpool"),

new threadpoolexecutor.callerrunspolicy());

假設,所有的任務都永遠無法執行完。

對於首先來的a,b來說直接執行,接下來,如果來了c,d,他們會被放到queue中,如果接下來再來e,f,則增加執行緒執行e,f。但是如果再來任務,佇列無法再接受了,執行緒數也到達最大的限制了,所以就會使用拒絕策略來處理。

執行緒池使用

1.定義乙個執行緒池,用來執行實現callable介面的任務類.當阻塞佇列新添乙個任務類時,將while迴圈新增設定乙個變數startexcute,當阻塞佇列新添第乙個任務時,將startexcute設定為true,並呼叫excutetaskcall方法,使用執行緒池執行阻塞佇列的任務。當阻塞隊列為...

使用執行緒和執行緒池

1 new thread的弊端 執行乙個非同步任務你還只是如下new thread嗎?new thread new runnable start 那你就out太多了,new thread的弊端如下 a.每次new thread新建物件效能差。b.執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭...

執行緒池的使用

簡而言之 兩個類 執行緒池的 類 public class threadpoolproxyfactory return mnormalthreadpoolproxy return public static threadpoolproxy createdownloadthreadpoolproxy ...