【進階之路】執行緒池拓展與CompletionService操作非同步任務
阿新 • • 發佈:2020-12-22
> 大家好,我是練習java兩年半時間的南橘,小夥伴可以一起互相交流經驗哦。
## 一、擴充套件ThreadPoolExecutor
### 1、擴充套件方法介紹
![](https://img-blog.csdnimg.cn/img_convert/b805ebf5547556a68e75a50a655a0f91.png)
ThreadPoolExecutor是可以擴充套件的,它內部提供了幾個可以在子類中改寫的方法(紅框內)。JDK內的註解上說,這些方法可以用以新增日誌,計時、監視或進行統計資訊的收集。是不是感覺很熟悉?有沒有一種**spring aop**中 @Around @Before @After三個註解的既視感?
我們來對比一下
| ThreadPoolExecutor| spring aop |
|------|------------|
| beforeExecute()(**執行緒執行之前呼叫**) | @Before(**在所攔截的方法執行之前執行** ) |
| afterExecute() (**執行緒執行之後呼叫**) |@After (**在所攔截的方法執行之後執行**) |
| terminated() (**執行緒池退出時候呼叫**) | |
| | @Around(**可以同時在所攔截的方法前後執行**) |
其實他們的效果是一樣的,只是一個線上程池裡,一個在攔截器中。
對於ThreadPoolExecutor中的這些方法,有這樣的一些特點:
- 1、**無論任務時從run中正常返回,還是丟擲一個異常而返回,afterExecute都會被呼叫**(但是如果任務在完成後帶有一個Error,那麼就不會呼叫afterExecute)
- 2、同時,**如果beforeExecute丟擲一個RuntimeExecption,那麼任務將不會被執行,連帶afterExecute也不會被呼叫了**。
- 3、**線上程池完成關閉操作時會呼叫terminated,類似於try-catch中的finally操作一樣。terminated可以用來釋放Executor在其生命週期裡分配的各種資源,此外也可以用來執行傳送通知、記錄日誌亦或是收集finalize統計資訊等操作**。
### 2、擴充套件方法實現
我們先構建一個自定義的執行緒池,它通過擴充套件方法來新增日誌記錄和統計資訊的收集。為了測量任務的執行時間,beforeExecute必須記錄開始時間並把它儲存到一個afterExecute可以訪問的地方,於是用ThreadLocal來儲存變數,用afterExecute來讀取,並通過terminated來輸出平均任務和日誌訊息。
```
public class WeedThreadPool extends ThreadPoolExecutor {
private final Thr