執行緒池框架執行流程和原理分析

2021-10-09 09:21:14 字數 3104 閱讀 1583

使用執行緒池的優勢:

重用存在的執行緒,減少執行緒建立,消亡的開銷,提高效能 提高響應速度。當任務到達時,任務可以不需要的等到執行緒建立就能立即執行。 提高執行緒的可管理性。執行緒是稀缺資源,如果無限制的建立,不僅會消耗系統資 源,還會降低系統的穩定性,使用執行緒池可以進行統一的分配,調優和監控。

1.執行緒池工具類:

單例執行緒池

定長線程池

延時執行緒池

週期執行執行緒池

執行緒池threadpoolexecutor

核心引數

corepoolsize 執行緒池中的核心執行緒數,當提交乙個任務時,執行緒池建立乙個新執行緒執行任務,直到當 前線程數等於corepoolsize;如果當前執行緒數為corepoolsize,繼續提交的任務被儲存到 阻塞佇列中,等待被執行;如果執行了執行緒池的prestartallcorethreads()方法,執行緒池會 提前建立並啟動所有核心執行緒。 maximumpoolsize 執行緒池中允許的最大執行緒數。如果當前阻塞佇列滿了,且繼續提交任務,則建立新的線 程執行任務,前提是當前執行緒數小於maximumpoolsize; keepalivetime 執行緒池維護執行緒所允許的空閒時間。當執行緒池中的執行緒數量大於corepoolsize的時 候,如果這時沒有新的任務提交,核心執行緒外的執行緒不會立即銷毀,而是會等待,直到等待 的時間超過了keepalivetime; unitkeepalivetime的單位; workqueue 用來儲存等待被執行的任務的阻塞佇列,且任務必須實現runable介面,在jdk中提供 了如下阻塞佇列: 1、arrayblockingqueue:基於陣列結構的有界阻塞佇列,按fifo排序任務; 2、linkedblockingquene:基於鍊錶結構的阻塞佇列,按fifo排序任務,吞 吐量通常要高於arrayblockingquene; 3、synchronousquene:乙個不儲存元素的阻塞佇列,每個插入操作必須等到 另乙個執行緒呼叫移除操作,否則插入操作一直處於阻塞狀態,吞吐量通常要高於 linkedblockingquene; 4、priorityblockingquene:具有優先順序的無界阻塞佇列; threadfactory 它是threadfactory型別的變數,用來建立新執行緒。預設使用 executors.defaultthreadfactory() 來建立執行緒。使用預設的threadfactory來建立執行緒 時,會使新建立的執行緒具有相同的norm_priority優先順序並且是非守護執行緒,同時也設 置了執行緒的名稱。 handler

執行緒池的飽和策略,當阻塞佇列滿了,且沒有空閒的工作執行緒,如果繼續提交任務,必 須採取一種策略處理該任務,執行緒池提供了4種策略: 1、abortpolicy:直接丟擲異常,預設策略; 2、callerrunspolicy:用呼叫者所在的執行緒來執行任務; 3、discardoldestpolicy:丟棄阻塞佇列中靠最前的任務,並執行當前任務; 4、discardpolicy:直接丟棄任務; 上面的4種策略都是threadpoolexecutor的內部類。 當然也可以根據應用場景實現rejectedexecutionhandler介面,自定義飽和策略,如 記錄日誌或持久化儲存不能處理的任務。

大體執行流程

如果達到核心執行緒數,則會把任務加入到佇列裡面,

直到佇列建立滿了,

如果還有任新的任務進來,

那麼就會建立臨時執行緒,

來處理當前任務,

當建立臨時執行緒和核心執行緒達到最大執行緒數時,

就會走飽和策略,而飽和策略有四種

預設是直接拋異常

第二種由提交任務的執行緒來執行當前的任務

第三種是將佇列裡的丟棄阻塞佇列中靠最前的任務,並執行當前任務

第四重是直接拋棄當前任務

如果加入佇列之後,如果執行緒池關閉則移除任務,走拒絕策略。另一種情況任務加入佇列,但是執行緒池執行緒為空,則建立乙個執行緒等著,

加入佇列不成功,為什麼則會去嘗試再建立非核心執行緒來執行任務?

原因是有可能佇列滿了,但是非核心執行緒為達到最大執行緒數量。

詳細執行流程:

這裡重要的地方是第二個if判斷,目的是控制線程池的有效執行緒數量。由上文中的分析 可以知道,在執行execute方法時,如果當前執行緒池的執行緒數量超過了corepoolsize且小於 maximumpoolsize,並且workqueue已滿時,則可以增加工作執行緒,但這時如果超時沒 有獲取到任務,也就是timedout為true的情況,說明workqueue已經為空了,也就說明了 當前執行緒池中不需要那麼多執行緒來執行任務了,可以把多於corepoolsize數量的執行緒銷毀 掉,保持執行緒數量在corepoolsize即可。

當傳進來乙個任務時 執行addworker()方法,

1判斷執行緒池狀態

2判斷當前執行緒數是否大於核心執行緒,或者當前執行緒數大於最大執行緒數,如果大於返回false,則要麼加入佇列,要麼走拒絕策略。返回true就會

會建立乙個 worker類(worker實現runable介面,也是乙個可被執行並傳入任務),並傳入任務賦值給worker類裡的乙個runable型別的firtask變數,

然後在worker構造方法裡呼叫工廠建立乙個新的執行緒,賦給worker類裡的乙個thread型別的thread變數,

把worker物件傳進去,r然後呼叫該執行緒的start()方法,當該執行緒被cpu執行時,就會執行worker物件的run方法,

run方法裡呼叫runworker方法,並傳入worker物件,然後迴圈判斷是否要執行當前傳進來的worker任務,或者從佇列裡去獲取取任務來執行。

這段**是接著上面截圖的**:

worker構造方法:

worker物件的run方法:

執行緒池核心流程和邏輯

1.new乙個執行緒池,執行緒池7個引數含義 public threadpoolexecutor int corepoolsize,核心池大小 int maximumpoolsize,最大執行緒數 long keepalivetime,空閒時間,大於空閒時間的執行緒銷毀 timeunit unit,...

什麼是執行緒池?執行緒池的工作原理和使用執行緒池的好處

乙個執行緒池管理了一組工作執行緒,同時它還包括了乙個用於放置等待執行任務的任務佇列 阻塞佇列 預設情況下,在建立了執行緒池後,執行緒池中的執行緒數為0.當任務提交給執行緒池之後的處理策略如下 1 如果此時執行緒池中的數量小於corepoolsize 核心池的大小 即使執行緒池中的執行緒都處於空閒狀態...

什麼是執行緒池?執行緒池的工作原理和使用執行緒池的好處

乙個執行緒池管理了一組工作執行緒,同時它還包括了乙個用於放置等待執行任務的任務佇列 阻塞佇列 預設情況下,在建立了執行緒池後,執行緒池中的執行緒數為0.當任務提交給執行緒池之後的處理策略如下 1 如果此時執行緒池中的數量小於corepoolsize 核心池的大小 即使執行緒池中的執行緒都處於空閒狀態...