java併發線程池建議還是多多使用ThreadPoolExecutor的構造函數來設置自定義的線程池,先來看看這個構造函數的參數列表。
/**
* 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) {
通過這些參數列表我們就可以實現一個自定義的線程池了。
1)線程池中核心線程數,
2)線程池中最大線程數,
3)線程池中線程的最大空閒時間,超過這個時間空閒線程將被回收。
4)阻塞隊列的定義,你可以設置是ArrayList還是LinkedList的阻塞隊列,
5)線程工廠,還可以使用自定義的線程工廠,使線程池中的線程打上你自己獨有的標籤,方便調試。自定義線程工廠很簡單,只需要繼承ThreadFactory然後重寫newThread方法即可。
6)線程拒絕策略,典型的幾類線程池默認策略都是拋出異常,其實你可以自定義線程拒絕策略,目前ThreadPoolExecutor爲我們提供了4種策略,分別是:
A:ThreadPoolExecutor.AbortPolicy 直接拋出異常
B:ThreadPoolExecutor.DiscardPolicy 丟棄當前被拒絕的任務(而不拋出任何異常)
C:ThreadPoolExecutor.DiscardOldestPolicy 將緩衝區中最老的任務丟棄,然後重新嘗試接納被拒絕的任務
D:ThreadPoolExecutor.CallerRunsPolicy 在任務的提交方線程中運行被拒絕的任務
不滿足的話,自己還可以實現自定義的線程拒絕策略,實現方法也很簡單,只需要實現RejectedExecutionHandler接口中定義的方法即可。
利用上面提到的6個參數就可以實現一個自定義的線程池了。
這裏再說明一下什麼時候會觸發拒絕線程提交的handler,
1)池中線程數小於corePoolSize時,新任務都不排隊而是直接添加新線程。
2)池中線程數大於等於corePoolSize時,workQueue未滿,首選將新任務加入workQueue而不是添加新線程。
3)池中線程數大於等於corePoolSize時,workQueue已滿,但是線程數小於maximumPoolSize,添加新的線程來處理被添加的任務。
4)池中線程數大於等於corePoolSize,workQueue已滿,並且線程數大於等於maximumPoolSize時,新任務被拒絕,使用handler處理被拒絕的任務。