1. 使用线程池能解决两方面的问题
a) 减少线程调用开销,提升性能;
b) 通过限制线程数量达到限制程序资源占用的目的;
2. 线程创建的规则
线程数小于 corePoolSize 时,新提交的任务会直接通过创建新线程执行,即使线程池中的线程是空闲的;
线程数大于等于 corePoolSize 而又小于 maximumPoolSize 时,只有队列满了才会创建新线程执行任务;
当任务不能被放入队列,创建新线程又会超过 maximumPoolSize 时,该任务会被 rejected;
有一个超时时间设定,当线程数大于 corePoolSize 时,空闲时间超过超时阈值的线程会被销毁,
当然这个超时时间也可以同时应用于 corePoolSize,需要设置参数 allowCoreThreadTimeOut 为 True;
3. 任务的安置优先级:先使用 corePool -> 再使用队列 -> 最后使用 maximumPool
当 corePool 盛不下了,就先扔到队列里;
队列也盛不下了,就继续建线程,直到达到上限;
4. 涉及的几种 BlockingQueue(无外乎,队列容量为 0、有限长、无限长三种喽!)
SynchronousQueue : 不能存储任务(队列长度为 0),通常需要 maximumPoolSize 无界以避免抛 rejected;
LinkedBlockingQueue : 无界队列,永远也存不满, maximumPoolSize 相当于失效;
ArrayBlockingQueue : 有界队列,最正常的 BlockingQueue
5. 涉及的几种 reject 策略
AbortPolicy : 抛出一个异常
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
CallerRunsPolicy : 调用者自己执行
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
DiscardPolicy:丢弃当前任务
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
DiscardOldestPolicy:丢弃最老的任务
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
RejectedExecutionHandler:用户可以自定义自己的 reject 策略