Java线程池( 二 )


②判断阻塞队列是否已满 , 如果没满 , 则将新提交的任务存储在阻塞队列中 。如果满 , 则进行下一步流程 。
③判断线程池中的线程是否都处于工作状态 , 如果没有 , 则创建一个新的工作线程来执行任务 。如果线程池中所有的线程都处于工作状态 , 则交给饱和策略来处理这个任务 。

Java线程池

文章插图
 
ThreadPoolExecutor通用的构造函数为:
Java线程池

文章插图
 
参数说明如下
corePoolSize
  • 线程池基本大小 。提交一个任务到线程池时 , 线程池会创建一个新的线程来执行任务 。新任务提交时 , 当目前线程数小于corePoolSize , 即使有空闲的线程可以执行该任务 , 也会创建新的线程 。
  • 如果线程池中的线程数已经大于或等于corePoolSize , 则不会创建新的线程 。
  • 当一个ThreadPoolExecutor被初始创建后 , 所有核心线程并非立即开始 , 而是等到有任务提交的时刻 。但如果调用了prestartAllCoreThreads()方法 , 所有核心线程会立即启动 。
maximuPoolSize
  • 线程池允许创建的最大线程数 。当阻塞队列满 , 且线程数小于maximumPoolSize时 , 便可以创建新的线程执行任务 。
  • 如果使用无界阻塞队列 , 该参数无效 。
keepAliveTime
  • 线程池的工作线程空闲后 , 保持存活的时间 。如果任务多且任务执行时间较短 , 可以调大该值 , 提高线程利用率 。
  • 如果一个线程已经闲置的时间超过了存活时间 , 它将成为一个被回收的候选者 , 如果当前的池的大小超过了的corePoolSize , 线程池会终止它 。
unit
  • 与keepAliveTime相关联的时间单位 。可选值有DAYS、HOURS、MINUTES、毫秒、微妙、纳秒 。
workQueue
  • 用于保存等待执行的任务的阻塞队列 。ThreadPoolExecutor允许提供一个BlockingQueue来持有等待执行的任务 。任务排队有3种基本方法:无限队列、有限队列、同步移交 。队列的选择和很多其他的配置参数都有关系 , 比如池的大小等 。ThreadPoolExecutor推荐以下几种阻塞队列 。
  • LinkedBlockingQueue:线程安全的阻塞队列 , 先进先出(FIFO) 。可以指定容量(有限队列) , 也可以不指定(无限队列) , 不指定的话默认最大是Integer.MAX_VALUE 。如果所有的工作者线程都处于忙碌状态 , 新提交的任务将会在队列中等候 。如果新的任务持续快速到达 , 超过了它们被执行的速度 , 队列会无限制地增加 。线程池中能创建的最大线程数为corePoolSize指定的值 。
  • ArrayBlockingQueue:数组实现的有界阻塞队列 , 先进先出(FIFO) 。线程池中能创建的最大线程数为maximumPoolSize指定的值 。有界队列有助于避免资源耗尽 , 当队列满时 , 如果还有新的任务到达 , 将根据饱和策略(也称拒绝策略)进行处理 。对于一个有界队列 , 队列的长度与池的长度必须一起调节 。一个大队列和一个小池 , 可以控制对内存和CPU的使用 , 也可以减少上下文切换 , 但相应的吞吐量也会减小 。
  • SynchronousQueue:SynchronousQueue并不是一个真正的队列 , 而是一种管理直接在线程间移交信息的机制 。当新任务到达时 , 如果所有工作线程都处于忙碌状态 , 且线程池数量小于maximumPoolSize , 就会创建一个新的线程 。否则根据饱和策略处理 。只有池是无限的 , 或者可以接受任务被拒绝 , SynchronousQueue才是一个有实际价值的选择 。
  • PriorityBlokingQueue: 一个支持优先级的无界阻塞队列。使用该队列 , 线程池中能创建的最大线程数为corePoolSize 。
threadFactory
  • 线程池创建线程时使用的线程工厂 , 可以不指定该参数 , 使用默认的线程工厂Executors.defaultThreadFactory() 。
handler
饱和策略 , 也称拒绝策略 。当有限队列满且线程池满的情况下 , 新的任务到达后 , 饱和策略将进行处理 。有以下几种:


推荐阅读