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处理被拒绝的任务。