最近項目中為了提高用戶體驗度,前台創建任務后台任務,用多線程來跑。
現在的場景:后台定時任務管理這兩個線程池,一個最大線程數10個,一個最大線程數15。應用部署之后,不超過5個小時,服務器負載高,內存使用過多。
分析原因:因為這個功能是excel導入功能,如果前台有大量的導入任務時,那么后台的負載就會很高。
我的實現原理:定時任務讀取任務,放到任務隊列表中,然后使用線程池消費任務隊列中的任務,每個線程時一直循環取任務。
我的定時任務周期是 1 分鍾,線程池從初始化時,空閑線程存活的時間為 1 分鍾,任務隊列沒有設定最大數量值。
優化:
1.任務隊列沒有上限
定時任務每次啟動都回去數據庫中讀取任務,放入對列表中,如果一直往任務隊列中放,那么任務隊列占用的內存會越來越大,導致服務器內存不足。
解決辦法:定時任務在讀取任務時,先判斷任務隊列的大小,比如我這設置的100個,那么我就不再讀取新的任務了。這個參數需要通過觀察機器的負載,然后來調整。
2.線程池中的線程,無限循環處理任務,當任務數量過多的時候,線程會一直執行,停不下來。
線程池中的線程,無限循環處理任務,當任務數量過多的時候,線程會一直執行,停不下來。
解決辦法:在線程內部設置計數器,當一個線程累計到一定數量,退出循環,然后清空資源,回收,間歇性,周期的執行任務,相當於定期回收資源
3.定時任務 1 分鍾,那么空閑線程存活的時間為1分鍾
由於空閑線程存活時間是 1 分鍾,那么我的定時任務也是 1 分鍾,這個時候,線程就基本就不會被線程池回收,那么資源就一直沒有釋放,被回收。
解決辦法:調整線程空閑的線程存活時間為定時任務周期的一半,也就是30秒。
4.在線程池中,有核心線程,對於核心線程超時也回收,所以,需要執行下邊這個方法,確保核心線程超時之后也被回收。
解決辦法:threadPoolExecutor.allowCoreThreadTimeOut(true);
優化之后的流程:
任務定期讀取任務,往任務隊列中放一定量(不能超過最大值)的任務,之后線程池中的線程超時時間設置短一點,線程通過計數器,當執行了一定數量的線程之后,推出循環,這個時候線程就空閑了,后邊就會被線程池回收,資源被回收,如此反復進行下去,資源回收,重新分配,不會大量消耗服務資源。
通過以上幾個點的優化,程序消耗服務器資源好很多,可能還有優化的地方,后邊再補充。