1、构造方法:
ThreadPoolExecutor类提供了四个构造方法,前三个最后都调用最后一个参数最全的方法:
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; }
2、参数说明:
corePoolSize:核心线程池数,创建的线程达到该数量后,即使有空闲的线程也不会释放。
maximumPoolSize:最大线程池数,创建的线程不会大于该数,超过核心线程池数corePoolSize并且等待队列满了之后才会继续创建线程直到达到最大线程池数。
keepAliveTime:空闲时间,超过corePoolSize的线程如果空闲时间超过keepAliveTime,线程会被回收。
unit:keepAliveTime的单位。
workQueue:任务等待队列,具体实现类:ArrayBlockingQueue,LinkedBlockingQueue,SynchronousQueue,PriorityBlockingQueue 。
threadFactory:线程工厂,用来创建线程,调用newThread(Runnable r)方法。
handler:拒绝策略,任务队列满了并且达到最大线程池数后触发拒绝策略;AbortPolicy(默认),CallerRunsPolicy,DiscardOldestPolicy,DiscardPolicy
3、workQueue任务队列说明:
ArrayBlockingQueue:有界队列,先进先出,需初始化队列大小,如果队列满了且线程达到最大线程池数后会触发拒绝策略。
LinkedBlockingQueue:*队列,先进先出,无需设置大小,超过核心线程池数后会不断往队列添加任务,直到内存溢出。
SynchronousQueue:阻塞队列,内部没有容器,每次put一个任务进去都得等待take方法消费完才能再put,可以理解为长度为1的队列。Executors.newCachedThreadPool内部使用的就是这个队列。
PriorityBlockingQueue:优先级队列,优先级高的任务会优先执行,队列中的元素必须实现Comparable接口。
4、拒绝策略说明:
AbortPolicy:默认的拒绝策略,会抛出RejectedExecutionException异常。
DiscardPolicy:直接拒绝,不抛异常。
DiscardOldestPolicy:丢弃最早添加的再尝试添加。
CallerRunsPolicy:由调用者直接执行。
Q:为什么线程达到核心线程池数之后是先放到等待队列而不是再继续创建新线程直到达到最大线程池数?
A:线程的创建需要获取全局锁,其他线程会被阻塞,所以等待队列起到一个缓冲作用;线程的创建和销毁都会消耗资源,这样做也是为了避免频繁的创建和销毁线程。