线程池

线程池

起男 1,451 2020-07-06

线程池

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线程池最大线程数量

  1. 一个任务提交到线程池后,首先会缓存到工作队列
  2. 如果队列满了,则会创建一个线程
  3. 然后从工作队列中取出一个任务交由新线程处理
  4. 新提交的任务放入工作队列

线程池不会无限的去创建新线程,数量由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 线程池关闭等待时间

执行流程

  1. 当一个任务通过submit或者execute方法提交到线程池时,如果当前池的线程数(包括空闲线程)小于coolPoolSize,则创建一个线程执行该任务
  2. 如果当前线程池中线程数已经达到coolPoolSize,则将任务放入等待队列
  3. 如果任务不能入队,说明等待队列已满,若当前线程池中线程数小于maximumPoolSize,则创建一个临时线程(非核心线程)执行该任务
  4. 如果当前线程池中线程数已经等于maximumPoolSize,此时无法执行该任务根据拒绝执行策略处理

当池中线程数大于coolPoolSize,超过keepAliveTime时间的闲置线程会被回收掉。

回收的是非核心线程,核心线程一般是不会被回收的。

如果设置allowCoreThreadTimeOut(true),则核心线程在闲置keepAliveTime时间后也会被回收