使用ExecutorService時遇到的坑


線上服務中有個使用 Spring 的scheduling.quartz的定時任務,每天凌晨1點向表里面灌初始數據,一個線程一台服務器在跑,剛上線的時候4個小時跑完,后來隨着用戶的激增,要下下午6點才結束,后來同事做了多線程優化,效果不顯著,耗時依舊嚴重,Zzzzzzz~~~~

 

於是clone 代碼看了下,感覺ExecutorService的使用怪怪的:

// 10個線程,因為任務多,這里用LinkedBlockingQueue
    private static final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
    private static final ExecutorService service = new ThreadPoolExecutor(0, 10,
            60L, TimeUnit.SECONDS, queue
    );
 
        

ExecutorService 的參數定義:

1.當線程池小於corePoolSize時,新提交任務將創建一個新線程執行任務,即使此時線程池中存在空閑線程。
2.當線程池達到corePoolSize時,新提交任務將被放入workQueue中,等待線程池中任務調度執行
3.當workQueue已滿,且maximumPoolSize>corePoolSize時,新提交任務會創建新線程執行任務

4.當提交任務數超過maximumPoolSize時,新提交任務由RejectedExecutionHandler處理 

5.當線程池中超過corePoolSize線程,空閑時間達到keepAliveTime時,關閉空閑線程

 

容易產生錯誤的理解:

代碼中的corePoolSize=0,也就是核心線程數是1,如果任務數多於10個,那么會先創建maximumPoolSize個線程執行,其余的任務加入 queue 中等待執行。

再看下類ThreadPoolExecutor中的注釋:

* When a new task is submitted in method {@link #execute}, and fewer
* than corePoolSize threads are running, a new thread is created to
* handle the request, even if other worker threads are idle.  If
* there are more than corePoolSize but less than maximumPoolSize
* threads running, a new thread will be created only if the queue is * full. 

注意紅色部分,而我們代碼中的 queue 是個類似無界的LinkedBlockingQueue(其實是有界的,SIZE:Integer.MAX_VALUE)

queue 是不會 full 的,那么永遠不會有maximumPoolSize個線程被創建,也就是說我們的任務一直還是一個線程在跑.......

 

果然只是把這個數字corePoolSize改為了3,耗時瞬間下降到了6、7個小時。又加了一台機器,依照業務主鍵的 ID 分布式跑任務,初始數據耗時縮減至3個小時左右!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM