/**
* Creates a new {@code ThreadPoolExecutor} with the given initial
* parameters.
*
* @param corePoolSize the number of threads to keep in the pool, even
* if they are idle, unless {@code allowCoreThreadTimeOut} is set
* @param maximumPoolSize the maximum number of threads to allow in the
* pool
* @param keepAliveTime when the number of threads is greater than
* the core, this is the maximum time that excess idle threads
* will wait for new tasks before terminating.
* @param unit the time unit for the {@code keepAliveTime} argument
* @param workQueue the queue to use for holding tasks before they are
* executed. This queue will hold only the {@code Runnable}
* tasks submitted by the {@code execute} method.
* @param threadFactory the factory to use when the executor
* creates a new thread
* @param handler the handler to use when execution is blocked
* because the thread bounds and queue capacities are reached
* @throws IllegalArgumentException if one of the following holds:<br>
* {@code corePoolSize < 0}<br>
* {@code keepAliveTime < 0}<br>
* {@code maximumPoolSize <= 0}<br>
* {@code maximumPoolSize < corePoolSize}
* @throws NullPointerException if {@code workQueue}
* or {@code threadFactory} or {@code handler} is null
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
<pre name="code" class="java">/**
* Set containing all worker threads in pool. Accessed only when
* holding mainLock.
*/
private final HashSet<Worker> workers = new HashSet<Worker>();
ThreadPoolExecutor 類的邏輯處理集中在8個屬性上面,上面是8個屬性構造源碼
workers : 線程池 ,Worker是其內部類,沒個Worder含有一個線程
corePoolSize : 線程池中最小活動線程
maximumPoolSize : 線程池中最大允許線程數
workQueue : 緩存隊列
keepAliveTime : 線程池中空閒線程最大存活時間
TimeUnit : keepAliveTime的單位
threadFactory : 新建線程時工廠類
handle : 處理被拒絕線程的處理類
執行過程,如我們上篇的圖,也如上面源碼中的英文註釋 (至於執行源碼,有點地方還沒弄通,就不寫分析了)
當新來任務的時候,
1、如果線程池小於corePoolSize , 那麼新建線程執行該任務
2、如果線程池大於等於corePoolSize , 那麼就往workQueue中添加
3、如果workQueue滿了且線程池小於maximumPoolSize ,那麼就新建線程執行任務
4、如果workQueue滿了且線程池等於maximumPoolSize ,那麼就拒絕任務 。
至於緩存中的線程是如何執行的呢 ?
在每個新建線程中都有這麼一段等效代碼 加在原任務執行結束後:
while( task = workQueue.poll(keepAliveTime ,TimeUnit ) ) {task.run();}
即線程執行任務完後會最大阻塞等待keepAliveTime 時間,直到從緩存隊列workQueue中獲取任務 (這段時間內稱線程爲閒置線程)。
獲取到新任務就執行,沒獲取到,那麼線程結束。
至於常見的Executors中的幾個構建對象源碼如下,大家自己理解嘍:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}//無限緩存,有nThreads個線程能夠併發執行任務,閒置時間爲0 ,即執行完任務瞬間找不到新任務就關閉線程
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
} //無限緩存,只有一個線程順訊的執行放進來的任務,閒置時間爲0,即執行完任務瞬間找不到新任務就關閉線程
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
} //0緩存,每新來個任務都看是否有閒置線程,有就使用閒置線程執行,否則新建線程 。 線程最大閒置時間60s
一般情況上訴3個已經滿足,如果大家另有需求就自行構建嘍 。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(5, 10,
1L, TimeUnit.SECONDS,
new ArrayBlockingQueue<Runnable>(5)));
}