线程池
Executors提供的线程池
- newSingleThreadExecutor
- 单线程线程池
- 会使用唯一的工作线程执行任务,保证所有线程按照指定的顺序执行
- newFixedThreadPool
- 定长线程池
- 可以控制最大并发数,超出的线程会在队列中等待
- newCachedThreadPool
- 可缓存线程池
- 当线程池数量超过需要,可灵活回收
- newScheduledThreadPool
- 可定期或延时执行任务的定长线程池
- 支持定时或周期性执行任务
- newSingleThreadScheduledExecutor
- 可定期或延时执行的单线程线程池
- 池内最多执行一个线程,之后提交的线程会排在队列中
- 支持定时或周期性执行任务
- newWorkStealingPool
- 因为能够合理使用cpu进行任务操作,所以适合很耗时的操作
- 使用ForkJoinPool
ThreadPoolExecutor参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize线程池核心线程大小
- 线程池中线程的最小数量
- 即使空闲也不会销毁
maximumPoolSize线程池最大线程数量
- 一个任务提交到线程池后,首先会缓存到工作队列
- 如果队列满了,则会创建一个线程
- 然后从工作队列中取出一个任务交由新线程处理
- 新提交的任务放入工作队列
线程池不会无限的去创建新线程,数量由maximumPoolSize控制
keepAliveTime空闲线程存活时间
一个线程处于空闲状态,并且当前的线程数大于核心线程数,那么在指定时间后,这个线程会被销毁
unit空间线程存活时间单位
keepAliveTime的计量单位
workQueue工作队列
任务提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务
- ArrayBlockingQueue:基于数组的有界阻塞队列,按fifo排序。有新任务会放在队列的队尾,有界数组可以防止资源耗尽
- LinkedBlockingQueue:基于链表的有界阻塞队列,按fifo排序。默认值为Integer.MAX_VALUE,所以我们在使用LinkedBlockingQueue时建议手动传值
- SynchronousQueue:一个不缓存任务的阻塞队列。有新任务时,不会缓存,直接执行,如果没有可用的线程,则会创建,如果达到最大,则执行拒绝策略
- PriorityBlockingQueue:具有优先级的无界阻塞队列。优先级通过参数实现
threadFactory线程工厂
- 创建一个线程池时使用的工厂
- 可以用来设定线程名,是否为daemon线程等
- 可以使用Executors默认提供的defaultThreadFactory()
handler拒绝策略
当工作队列达到最大,并且线程池中的线程数量也达到最大,如果再有任务提交,则执行拒绝策略
- CallerRunsPolicy:由调用线程处理该任务
- AbortPolicy:直接丢弃任务,并抛出异常
- DiscardPolicy:直接丢弃任务,什么都不做
- DiscardOldestPolicy:丢弃最早提交的任务,然后重新提交被拒绝的任务
常用api
方法名 | 作用 |
---|---|
execute | 执行一个任务,没有返回值 |
submit | 执行一个任何,可以有返回值 |
invokeAny | 接收一个任务集合,返回其中一个的结果 |
invokeAll | 接收一个任务集合,返回一个结果的集合 |
shutdwon | 等待正在执行的任务执行完毕关闭线程池 |
shutdwonNow | 会终止所有正在执行的任务并关闭线程池 |
isTerminated | 判断是否已终止线程池 |
awaitTermination | 线程池关闭等待时间 |
执行流程
- 当一个任务通过submit或者execute方法提交到线程池时,如果当前池的线程数(包括空闲线程)小于coolPoolSize,则创建一个线程执行该任务
- 如果当前线程池中线程数已经达到coolPoolSize,则将任务放入等待队列
- 如果任务不能入队,说明等待队列已满,若当前线程池中线程数小于maximumPoolSize,则创建一个临时线程(非核心线程)执行该任务
- 如果当前线程池中线程数已经等于maximumPoolSize,此时无法执行该任务根据拒绝执行策略处理
当池中线程数大于coolPoolSize,超过keepAliveTime时间的闲置线程会被回收掉。
回收的是非核心线程,核心线程一般是不会被回收的。
如果设置allowCoreThreadTimeOut(true),则核心线程在闲置keepAliveTime时间后也会被回收