Java ThreadPool - Custom

Java 线程池简要-自定义线程池

自定义线程池

直接看源码,自定义线程池的几个关键参数

1
2
3
4
5
6
7
8
9
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
Executors.defaultThreadFactory(), handler);
}

几个核心参数:

  • corePoolSize - 即时空闲也会保持的核心线程数量
  • maximumPoolSize - 池中最大线程数量
  • keepAliveTime - 超过核心数量后,等待接收任务的最大时间
  • unit - keepAliveTime 参数的单位
  • workQueue - 执行之前排队的缓存队列
  • handler - 线程数和队列数都达到最大值后的处理器

新任务来了之后的流程

直接看javadoc怎么说的,已经很详细了:

  • 核心数和最大线程数:
    ThreadPoolExecutor会根据核心线程数和最大线程数不断调整线程池大小。
    当新的任务通过 execute()方法提交后:

    1. 当前线程数 < corePoolSize : 会创建一个新线程处理请求,即时有其他的空闲线程
    2. 当前线程数 > corePoolSize 但是队列还没满 -> 任务加入队列
      队列如果也满了,并且当前线程数 < maximumPoolSize : 创建一个新线程处理请求
    3. corePoolSize = maximumPoolSize : 固定大小的线程池
    4. maximumPoolSize = Integer.MAX_VALUE,线程池处理任意数量的并发任务
      一般来说,core 和 maximum 的值是构造的时候指定,但也可以通过方法动态调整
  • 按需创建
    默认的话即时核心前程也是有新任务的时候才创建,但是可以通过方法覆盖此策略。

  • 创建新的线程
    通过 ThreadFactory 创建新的线程,不指定就用默认的。
    创建的线程有相同的 ThreadGroup,优先级,都是非守护线程的状态。
    提供一个不同的 ThreadFactory ,即可修改这些策略。

  • Keep-alive 时间
    超过 corePoolSize 的时候,如果有空闲线程,那边就会被终结。之后有需求会重新创建

  • Queuing
    任何的 BlockingQueue 都可以用来传递、持有提交的任务。

    • 小于 corePoolSize ,创建新线程,不加到队列
    • 大于 corePoolSize , 总是加入队列而不是创建新线程
    • 如果无法加入队列,创建新线程直到达到 maximumPoolSize。超过了则任务被拒
      主要有3种加入队列的策略:
    • SynchronousQueue (待补充)
    • LinkedBlockingQueue (待补充)
    • ArrayBlockingQueue (待补充)
  • 拒绝任务
    线程池已经关闭 or 队列和线程全部饱和,会触发任务拒绝处理,默认有4个预置策略

    • 抛出运行时异常(默认)
    • 发起execute线程自己执行任务
    • 直接扔掉
    • 扔掉最早的任务
  • 钩子方法
    开始和结束执行任务时提供钩子方法。可以做一些:初始化ThreadLocal,统计,加日志等

  • 队列维护

  • 终结