线程池主要参数有哪些?
线程池有 7 个参数,需要重点关注corePoolSize、maximumPoolSize、workQueue、handler 这四个。
线程池参数
①、corePoolSize
定义了线程池中的核心线程数量。即使这些线程处于空闲状态,它们也不会被回收。这是线程池保持在等待状态下的线程数。
②、maximumPoolSize
线程池允许的最大线程数量。当工作队列满了之后,线程池会创建新线程来处理任务,直到线程数达到这个最大值。
③、keepAliveTime
非核心线程的空闲存活时间。如果线程池中的线程数量超过了 corePoolSize,那么这些多余的线程在空闲时间超过 keepAliveTime 时会被终止。
④、unit
keepAliveTime 参数的时间单位:
- TimeUnit.DAYS; 天
- TimeUnit.HOURS; 小时
- TimeUnit.MINUTES; 分钟
- TimeUnit.SECONDS; 秒
- TimeUnit.MILLISECONDS; 毫秒
- TimeUnit.MICROSECONDS; 微秒
- TimeUnit.NANOSECONDS; 纳秒
⑤、workQueue 用于存放待处理任务的阻塞队列。当所有核心线程都忙时,新任务会被放在这个队列里等待执行。 ⑥、threadFactory 一个创建新线程的工厂。它用于创建线程池中的线程。可以通过自定义 ThreadFactory 来给线程池中的线程设置有意义的名字,或设置优先级等。 ⑦、handler 拒绝策略 RejectedExecutionHandler,定义了当线程池和工作队列都满了之后对新提交的任务的处理策略。常见的拒绝策略包括抛出异常、直接丢弃、丢弃队列中最老的任务、由提交任务的线程来直接执行任务等。 它们之间的关系如下: ①、corePoolSize 和 maximumPoolSize 共同定义了线程池的规模。
- 当提交的任务数不足以填满核心线程时,线程池只会创建足够的线程来处理任务。
- 当任务数增多,超过核心线程的处理能力时,任务会被加入 workQueue。
- 如果 workQueue 已满,而当前线程数又小于 maximumPoolSize,线程池会尝试创建新的线程来处理任务。
②、keepAliveTime 和 unit 决定了非核心线程可以空闲存活多久。这会影响了线程池的资源回收策略。 ③、workQueue 的选择对线程池的行为有重大影响。不同类型的队列(如无界队列、有界队列)会导致线程池在任务增多时的反应不同。 ④、handler 定义了线程池的饱和策略,即当线程池无法接受新任务时的行为。决定了系统在极限情况下的表现。
举个例子说一下这些参数的变化
假设一个场景,线程池的配置如下:
corePoolSize = 5maximumPoolSize = 10keepAliveTime = 60秒workQueue = LinkedBlockingQueue(容量为100)默认的threadFactoryhandler = ThreadPoolExecutor.AbortPolicy()场景一:当系统启动后,逐渐有 10 个任务提交到线程池。
- 前 5 个任务会立即执行,因为它们会占用所有的核心线程。
- 随后的 5 个任务会被放入工作队列中等待执行。
场景二:如果此时再有 100 个任务提交到线程池。
- 工作队列已满,线程池会创建额外的线程来执行这些任务,直到线程总数达到 maximumPoolSize(10 个线程)。
- 如果任务继续增加,超过了工作队列和最大线程数的限制,新来的任务将会根据拒绝策略(AbortPolicy)被拒绝,抛出 RejectedExecutionException 异常。
场景三:如果任务突然减少,只有少量的任务需要执行: 核心线程会一直运行,而超出核心线程数的线程,如果空闲时间超过 keepAliveTime,将会被终止,直到线程池的线程数减少到 corePoolSize。