天天看點

ThreadPoolExecutor運作機制

最近發現幾起對threadpoolexecutor的誤用,其中包括自己,發現都是因為沒有仔細看注釋和内部運轉機制,想當然的揣測參數導緻,先看一下建立一個threadpoolexecutor的建構參數:

public threadpoolexecutor(int corepoolsize,  

                          int maximumpoolsize,  

                          long keepalivetime,  

                          timeunit unit,  

                          blockingqueue<runnable> workqueue,  

                          threadfactory threadfactory,  

                          rejectedexecutionhandler handler)  

看這個參數很容易讓人以為是線程池裡保持corepoolsize個線程,如果不夠用,就加線程入池直至maximumpoolsize大小,如果還不夠就往workqueue裡加,如果workqueue也不夠就用rejectedexecutionhandler來做拒絕處理。

但實際情況不是這樣,具體流程如下:

1)當池子大小小于corepoolsize就建立線程,并處理請求

2)當池子大小等于corepoolsize,把請求放入workqueue中,池子裡的空閑線程就去從workqueue中取任務并處理

3)當workqueue放不下新入的任務時,建立線程入池,并處理請求,如果池子大小撐到了maximumpoolsize就用rejectedexecutionhandler來做拒絕處理

4)另外,當池子的線程數大于corepoolsize的時候,多餘的線程會等待keepalivetime長的時間,如果無請求可處理就自行銷毀

内部結構如下所示:

ThreadPoolExecutor運作機制

從中可以發現threadpoolexecutor就是依靠blockingqueue的阻塞機制來維持線程池,當池子裡的線程無事可幹的時候就通過workqueue.take()阻塞住。

其實可以通過executes來學學幾種特殊的threadpoolexecutor是如何建構的。

public static executorservice newfixedthreadpool(int nthreads) {  

    return new threadpoolexecutor(nthreads, nthreads,  

                                  0l, timeunit.milliseconds,  

                                  new linkedblockingqueue<runnable>());  

}  

newfixedthreadpool就是一個固定大小的threadpool

public static executorservice newcachedthreadpool() {  

    return new threadpoolexecutor(0, integer.max_value,  

                                  60l, timeunit.seconds,  

                                  new synchronousqueue<runnable>());  

newcachedthreadpool比較适合沒有固定大小并且比較快速就能完成的小任務,沒必要維持一個pool,這比直接new thread來處理的好處是能在60秒内重用已建立的線程。

其他類型的threadpool看看建構參數再結合上面所說的特性就大緻知道它的特性