天天看點

實戰 | 線程池的幾種自定義擴充

下圖為線程池的構造方法,我們可以自定義一些功能實作項目優化

this.prestartAllCoreThreads();

使用方式:自定義線程池的構造方法中調用

作用:當真正任務被執行時,可以減少建立線程帶來的性能損耗

實戰 | 線程池的幾種自定義擴充

官方提供的預設線程池工廠為Executors.defaultThreadFactory();

我們可以仿照進行自定義擴充線程工廠,增加一些個性化功能。

如下圖所示,我們自定義線程池線程工廠時可以附加很多功能。

1、定制化線程池内線程名稱,便于我們線上上快速定位;

2、在建立線程時,設定其是否為守護線程 等等

實戰 | 線程池的幾種自定義擴充

線程池執行任務時(執行execute方法時),當任務抛出異常,線程池并沒有捕獲,是以直接導緻任務失敗,線程池線程銷毀【往期文章:線程池原理】。

工作中往往因為資訊的缺失,出現問題卻感覺不到而導緻線上事故,帶來損失

通過實作Thread的UncaughtExceptionHandler接口,為線程池線程設定異常處理類,進而達到任務異常感覺和捕獲

實戰 | 線程池的幾種自定義擴充

線程池執行任務,對我們而言是一個黑盒。

任務有可能直接被執行;也可能暫存到隊列,長時間無法被執行導緻系統性能降低;又或者任務被丢棄,以及被丢棄的數量。

因為這些不确定,在系統性能被影響時,無法采取合理的方式進行調整。

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

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拒絕政策,可以監控被拒絕任務的執行耗時、可用率、執行次數等資訊

以上的可擴充的方法可以抽象出來,面向接口程式設計 通過責任鍊模式處理多種業務

使用zookeeper動态修改線程池參數

5.1、線程池提供了線程數、空閑時間等資訊的set方法

實戰 | 線程池的幾種自定義擴充

5.2、自定義可修改大小的隊列

修改隊列的方式可以檢視上期文章:動态修改線程池隊列大小

RunTime.getRunTime().addShutdownHook的作用就是在JVM銷毀前執行的一個線程

任務進入最終态(任務執行完成、異常、取消、打斷)時,調用unpark方法恢複因調用get()方法而挂起的線程,并調用done擴充空方法

futureTask任務結束後,會調用done空方法

實戰 | 線程池的幾種自定義擴充

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

使用場景:

1、批量任務處理,哪個任務的done方法先被調用,可以優先執行哪個任務。提高任務的處理速度

2、線上送出訂單時,往往需要同時消費多個資源。但隻要有一個資源消費失敗,所有資源都是要復原的。

是以可以通過done方法快速感覺處理快的任務。提前感覺到消費失敗的情況并做復原。進而提高效率

3、官方提供了一些done方法的功能

比如:ExecutorCompletionService将任務按照完成的先後順序,存儲到隊列中。并以此擷取處理

實戰 | 線程池的幾種自定義擴充
實戰 | 線程池的幾種自定義擴充

1、通過閱讀源碼,可以讓我們找到很多可擴充的方法,供我們自定義功能

2、檢視可擴充方法的具體實作,就可以找到官方提供的一些擴充實作,學習其中的使用

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

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

實戰 | 線程池的幾種自定義擴充