盤點java並發包提供的執行緒池和佇列

2021-08-21 05:05:26 字數 3171 閱讀 8775

執行緒池 佇列

執行緒池 executors框架的5個靜態工廠方法

經常用來處理短時間任務的執行緒池,它試圖快取執行緒並重用,如果沒有可用的快取執行緒則新建執行緒,如果執行緒閒置60秒會移出快取,這種執行緒池長時間閒置不會占用什麼資源,但是如果任務併發出現速度過快會導致執行緒建立來不及處理任務導致部分任務等待超時。

建立時接收快取執行緒數引數,它只會快取這麼多執行緒,不會多也不會少,如果有工作執行緒退出,會建立新的執行緒補足指定數目。

它的工作佇列是無界的,如果沒有執行緒可用則會在佇列中等待,這導致如果執行緒大小設定不合理以及任務併發大的情況下,請求型別的任務可能會導致請求超時。

為了避免上面的情況導致超時也好,佇列任務過多導致oom也好,可以使用jmap等工具,檢視是否有大量任務物件入隊。

它建立的是scheduledexecutorservice,可以定時或週期性的工作排程,執行緒數被限制為1,保證任務是順序執行,執行緒池例項不能被修改。

它建立的也是scheduledexecutorservice,區別在於它會保持核心執行緒在一定數量

內部構造forkjoinpool,利用work-stealing 演算法,並行處理任務,不保證處理順序。

threadpoolexecutor 建立執行緒

new  threadpoolexecutor(corepoolsize, maximumpoolsize, keepalivetime, milliseconds,runnabletaskqueue, handler);

• corepoolsize(執行緒池的基本大小):當提交乙個任務到執行緒池時,執行緒池會建立乙個執行緒來執行任務,即使其他空閒的基本執行緒能夠執行新任務也會建立執行緒,等到需要執行的任務數大於執行緒池基本大小時就不再建立。如果呼叫了執行緒池的prestartallcorethreads方法,執行緒池會提前建立並啟動所有基本執行緒。

• runnabletaskqueue(任務佇列):用於儲存等待執行的任務的阻塞佇列。 可以選擇以下幾個阻塞佇列。

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

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

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

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

• maximumpoolsize(執行緒池最大大小):執行緒池允許建立的最大執行緒數。如果佇列滿了,並且已建立的執行緒數小於最大執行緒數,則執行緒池會再建立新的執行緒執行任務。值得注意的是如果使用了無界的任務佇列這個引數就沒什麼效果。

• threadfactory:用於設定建立執行緒的工廠,可以通過執行緒工廠給每個建立出來的執行緒設定更有意義的名字。

• rejectedexecutionhandler(飽和策略):當佇列和執行緒池都滿了,說明執行緒池處於飽和狀態,那麼必須採取一種策略處理提交的新任務。這個策略預設情況下是abortpolicy,表示無法處理新任務時丟擲異常。以下是jdk1.5提供的四種策略。

• abortpolicy:直接丟擲異常。

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

• discardpolicy:不處理,丟棄掉。

• 當然也可以根據應用場景需要來實現rejectedexecutionhandler介面自定義策略。如記錄日誌或持久化不能處理的任務。

• keepalivetime(執行緒活動保持時間):執行緒池的工作執行緒空閒後,保持存活的時間。所以如果任務很多,並且每個任務執行的時間比較短,可以調大這個時間,提高執行緒的利用率。

• timeunit(執行緒活動保持時間的單位):可選的單位有天(days),小時(hours),分鐘(minutes),毫秒(milliseconds),微秒(microseconds, 千分之一毫秒)和毫微秒(nanoseconds, 千分之一微秒)。

向執行緒池提交任務

任務拒絕策略

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

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

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

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

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

自定義拒絕策略
/**

* 執行緒池 請求數 大於 最大執行緒數+佇列大小

*@author: duhongjiang

*@date: created in 2018/6/24

*/public

abstract

class

myrejectedexecutionhandler

implements

rejectedexecutionhandler

protected

abstract

void

rejected();

}

執行緒池容量的動態調整

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

• setcorepoolsize:設定核心池大小

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

佇列

這個佇列不會快取任務,也就是說佇列容量是0,來乙個任務就交給執行緒,是cachedthreadpool使用的佇列。

基於鍊錶的先進先出 無界的佇列,fixedthreadpool使用。但是 無界是相對說的,它的佇列大小預設是integer.max_value,當然也可以指定大小。

JAVA併發訪問 執行緒池

1.前言 在乙個 jvm 裡建立太多的執行緒可能會導致系統由於過度消耗記憶體而用完記憶體或 切換過度 為了防止資源不足,伺服器應用程式需要一些辦法來限制任何給定時刻處理的請求數目。2.執行緒池的作用 執行緒池為執行緒生命週期開銷問題和資源不足問題提供了解決方案。通過對多個任務重用執行緒,執行緒建立的...

Java併發 執行緒池原理

執行緒池是j.u.c中乙個非常常用的元件,利於執行緒池技術可以有效利於執行緒資源,避免頻繁的建立和銷毀執行緒造成的系統開銷,避免過多的建立執行緒耗盡系統資源,同時還可以更好對管理執行緒,包括關閉 中斷以及狀態監控等等。1.提交任務 2.核心執行緒數是否已滿 3.若核心執行緒數已滿,則將任務加入等待佇...

java併發程式設計 執行緒池

降低資源消耗 提高響應速度 t1 執行緒建立的時間 t2 工作任務執行額時間 t3 執行緒銷毀時間 提高了執行緒的可管理性 corepoolsize 核心執行緒數 如果執行的執行緒數大於核心執行緒數,則會先進入到阻塞佇列裡 maxinumpoolsize 允許最大執行緒數 執行緒池所建立的執行緒數一...