實戰 | 執行緒池的幾種自定義擴充套件

zy苦行僧發表於2021-10-28

下圖為執行緒池的構造方法,我們可以自定義一些功能實現專案優化
在這裡插入圖片描述

1、預先啟動核心執行緒

this.prestartAllCoreThreads();
使用方式:自定義執行緒池的構造方法中呼叫
作用:當真正任務被執行時,可以減少建立執行緒帶來的效能損耗
在這裡插入圖片描述

2、自定義執行緒池執行緒工廠

官方提供的預設執行緒池工廠為Executors.defaultThreadFactory();
我們可以仿照進行自定義擴充套件執行緒工廠,增加一些個性化功能。

如下圖所示,我們自定義執行緒池執行緒工廠時可以附加很多功能。
1、定製化執行緒池內執行緒名稱,便於我們線上上快速定位;
2、在建立執行緒時,設定其是否為守護執行緒 等等
在這裡插入圖片描述

3、感知並捕獲任務異常

執行緒池執行任務時(執行execute方法時),當任務丟擲異常,執行緒池並沒有捕獲,因此直接導致任務失敗,執行緒池執行緒銷燬【往期文章:執行緒池原理】。
工作中往往因為資訊的缺失,出現問題卻感知不到而導致線上事故,帶來損失

通過實現Thread的UncaughtExceptionHandler介面,為執行緒池執行緒設定異常處理類,從而達到任務異常感知和捕獲
在這裡插入圖片描述

4、執行緒池監控和告警

執行緒池執行任務,對我們而言是一個黑盒。
任務有可能直接被執行;也可能暫存到佇列,長時間無法被執行導致系統效能降低;又或者任務被丟棄,以及被丟棄的數量。
因為這些不確定,在系統效能被影響時,無法採取合理的方式進行調整。

以下幾個自定義功能,可以讓我們對其進行巨集觀的監控

4.1、使用輪詢獲取執行緒池內狀態資訊(不推薦)

執行緒池提供很多get方法獲取執行緒池內實時資訊,但大部分都是加鎖操作,頻繁使用會降低執行緒池處理任務的效率。
因此這種方式並不推薦。
在這裡插入圖片描述

4.2、根據執行緒池本身提供的鉤子,進行自定義擴充套件

4.2.1、執行每個任務的監控
執行緒池執行緒通過runWorker方法執行每個任務時,前後都提供了空方法,供自定義擴充套件。

執行任務前方法:beforeExecute(wt, task);
執行任務:task.run();
執行任務後方法:afterExecute(task, thrown);
在這裡插入圖片描述

以下為自定義擴充套件的例子:
beforeExecute(wt, task);方法擴充套件
在這裡插入圖片描述

afterExecute(task, thrown);方法擴充套件在這裡插入圖片描述
通過自定義beforeExecute和afterExecute方法,可以監控到任務執行耗時、可用率、執行次數等資訊

4.2.2、被拒絕的任務的監控
在這裡插入圖片描述
當任務被拒絕時,可以自定義CallerRunsPolicy拒絕策略來監控相關資訊


以下為自定義擴充套件的例子

在這裡插入圖片描述
通過自定義CallerRunsPolicy拒絕策略,可以監控被拒絕任務的執行耗時、可用率、執行次數等資訊

以上的可擴充套件的方法可以抽象出來,面向介面程式設計

通過責任鏈模式處理多種業務

5、執行緒池引數動態修改

使用zookeeper動態修改執行緒池引數

5.1、執行緒池提供了執行緒數、空閒時間等資訊的set方法
在這裡插入圖片描述
5.2、自定義可修改大小的佇列
修改佇列的方式可以檢視上期文章:動態修改執行緒池佇列大小


6、自定義關閉執行緒池

RunTime.getRunTime().addShutdownHook的作用就是在JVM銷燬前執行的一個執行緒


7、感知FutureTask任務的結束

任務進入最終態(任務執行完成、異常、取消、打斷)時,呼叫unpark方法恢復因呼叫get()方法而掛起的執行緒,並呼叫done擴充套件空方法

futureTask任務結束後,會呼叫done空方法
在這裡插入圖片描述

執行多個任務時,通過任務執行done方法的先後順序,可以感知任務執行完成的先後順序

使用場景:

1、批量任務處理,哪個任務的done方法先被呼叫,可以優先執行哪個任務。提高任務的處理速度
2、線上提交訂單時,往往需要同時消費多個資源。但只要有一個資源消費失敗,所有資源都是要回滾的。
因此可以通過done方法快速感知處理快的任務。提前感知到消費失敗的情況並做回滾。從而提高效率
3、官方提供了一些done方法的功能
比如:ExecutorCompletionService將任務按照完成的先後順序,儲存到佇列中。並以此獲取處理
在這裡插入圖片描述

在這裡插入圖片描述

8、總結

1、通過閱讀原始碼,可以讓我們找到很多可擴充套件的方法,供我們自定義功能
2、檢視可擴充套件方法的具體實現,就可以找到官方提供的一些擴充套件實現,學習其中的使用


------The End------




如果這個辦法對您有用,或者您希望持續關注,也可以掃描下方二維碼或者在微信公眾號中搜尋【碼路無涯】


相關文章