1.线程池
原因: 在使用多线程的时候,如果频繁的创建销毁线程会很消耗资源,资源开销大,所以就会用到线程池。
简单描述下核心线程数,最大线程数,队列
- 一个任务被提交时,线程池会判断核心线程数,
- 如果小于核心线程数,则会创建新的线程执行任务。
- 如果到达了核心线程数,就会放入到队列。
- 如果队列满了就判断最大线程数,
- 如果当前线程池的总线程数 小于 最大线程数,则创建新线程,否则执行拒绝策略。
2. ThreadPoolExecutor 参数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), defaultHandler);
}
corePoolSize : 核心线程数
线程池会维护一个核心线程数,即便是这些线程处在空闲状态也不会被销毁,除非设置了allowCoreThreadTimeOut。
当一个任务提交过来,线程池会检测当前线程的数量是不是小于核心线程数,
如果小于则创建一个新的线程执行任务
如果大于则会放到队列中
maximumPoolSize : 最大线程数
当线程中队列满的时候,这时候线程会继续创建新的线程。
但是不会一直创建新的线程,创建线程数量的多少是由maximumPoolSize 大小来定的
keepAliveTime :空闲线程存活时间
线程池中的线程数量大于核心线程数(corePoolSize)的线程,处于空闲状态,那么会在指定的时间后销毁
这个指定时间就是由:keepAliveTime 来指定。
unit : 单位
keepAliveTime 计量单位。
workQueue : 工作队列
ArrayBlockingQueue
基于数组的有界阻塞队列,按照FIFO进行排序。
1.有界限可以防止资源被耗尽。
2. 当线程池中的线程数达到核心线程数的时候,在有新的任务进来的时候,会放到队列的尾部,等待调用。
3. 如果队列满了,则创建新的线程,
4. 如果线程数达到了maximumPoolSize,则会执行拒绝策略。
LinkedBlockingQuene
基于链表的无解阻塞队列(最大:Interger.MAX(2^31-1)),按照FIFO 进行排序。
1.当线程池的线程数达到核心线程数,该队列容量过大,所以再有新的任务进来时会存入队列,基本不会创建新的线程。
SynchronousQuene
一个不缓存的阻塞队列
1. 当有新任务进来时,不会缓存该任务,而是等待调度执行该任务
2. 如果没有可用线程,则创建线程执行
3. 如果线程数达到最大线程数,则执行拒绝策略。
PriorityBlockingQueue
1. 具有优先级的无界阻塞对列,优先级通过参数Comparator实现。
拒绝策略:
CallerRunsPolicy
直接在调用者线程中执行被拒绝任务的run方法,除非线程池已经shutdown,则抛弃任务
AbortPolicy
直接抛弃任务,并抛出RejectedExecutionException异常。
DiscardPolicy
该策略下,直接丢弃任务,什么都不做。
DiscardOldestPolicy
抛弃进入队列最早的那个任务,并尝试将拒绝的任务放入到队列。