一文读懂线程池参数
面试过程中常问的线程池参数问题,你都掌握了吗?如果还没有,那么恭喜看到这篇文章的你。接下来就需要你花点时间,通过阅读文章,掌握线程池的各个参数。
线程池参数表
参数名 | 说明 | |
---|---|---|
corePoolSize | the number of threads to keep in the pool | 核心线程数 |
maximumPoolSize | the maximum number of threads to allow in the pool | 最大线程数 |
keepAliveTime | when the number of threads is greater than the core, this is the maximum time that excess idle threads will wait for new tasks before terminating. | 空闲线程存活时间 |
unit | the time unit for the {@code keepAliveTime} argument | 时间单位 |
workQueue | the queue to use for holding tasks before they are executed. This queue will hold only the {@code Runnable} tasks submitted by the {@code execute} method. | 用于存放任务的队列 |
threadFactory | the factory to use when the executor creates a new thread | 线程工厂,用于创建新线程 |
handler | the handler to use when execution is blocked because the thread bounds and queue capacities are reached | 处理被拒绝的任务 |
参数详细介绍
任务提交工作流程
提交任务后,线程池首先会检查当前线程数,如果此时线程数小于核心线程数,则新建线程并执行任务,随着任务的不断增加,线程数会逐渐增加并达到核心线程数,此时如果仍有任务被不断提交,就会被放入 workQueue 任务队列中,等待核心线程执行完当前任务后重新从 workQueue 中提取正在等待被执行的任务。
当任务达到了 workQueue 的容量上限,这时线程池就会使用备用线程,也就是 maximumPoolSize 最大线程数,线程池会在 corePoolSize 核心线程数的基础上继续创建线程来执行任务,假设任务被不断提交,线程池会持续创建线程直到线程数达到 maximumPoolSize 最大线程数,如果依然有任务被提交,这就超过了线程池的最大处理能力,这个时候线程池就会拒绝这些任务,我们可以看到实际上任务进来之后,线程池会逐一判断 corePoolSize、workQueue、maximumPoolSize,如果依然不能满足需求,则会拒绝任务。
corePoolSize 与 maximumPoolSize
-
corePoolSize 核心线程数
- 线程池初始化时线程数为 0,有新的任务提交后,会创建新的线程,直到线程数达到核心线程数。
- 核心线程一般不会被销毁
-
maximumPoolSize 最大线程数
随着任务量的增加,在任务队列满了之后,线程池会进一步创建新线程,最多可以达到 maximumPoolSize
当线程有空闲时,大于 corePoolSize 的线程会被合理回收
所以正常情况下,线程池中的线程数量会控制在 corePoolSize 至 maximumPoolSize 之间。
keepAliveTime 与 unit
-
keepAliveTime
- 当线程池中线程数大于核心线程数时,且处于空闲状态,线程池就会检测线程的 keepAliveTime,如果超过规定的时间,空闲的线程就会被销毁,以便减少内存的占用和资源消耗。
- 通过setKeepAliveTime 方法,可以动态改变 keepAliveTime 的参数值
-
unit
- 时间单位,配合 keepAliveTime 使用
ThreadFactory
- ThreadFactory
- 线程工厂,它的作用是生产线程以便执行任务。我们可以选择使用默认的线程工厂,创建的线程都会在同一个线程组,并拥有一样的优先级,且都不是守护线程,我们也可以选择自己定制线程工厂,以方便给线程自定义命名,不同的线程池内的线程通常会根据具体业务来定制不同的线程名。
workQueue 与 Handler
- workQueue
- 阻塞队列
- Handler
- 任务拒绝策略
线程池的特点
线程池希望保持较少的线程数,并且只有在负载变得很大时才增加线程。
线程池只有在任务队列填满时才创建多于 corePoolSize 的线程,如果使用的是无界队列(例如 LinkedBlockingQueue),那么由于队列不会满,所以线程数不会超过 corePoolSize。
通过设置 corePoolSize 和 maximumPoolSize 为相同的值,就可以创建固定大小的线程池。
通过设置 maximumPoolSize 为很高的值,例如 Integer.MAX_VALUE,就可以允许线程池创建任意多的线程
使用线程池的好处
- 降低资源消耗:通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 提高响应速度:当任务到达时,可以不需要等待线程创建就能立即执行。
- 提高线程的可管理性:线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,监控和调优。