urlname
type
Post
password
SyncToConfluence
category
学习笔记
date
Apr 25, 2024
slug
01HWA0YK3E0KZKS5514MN0J9GG
icon
Button
catalog
summary
tags
JUC
Java
线程池
多线程
cover
Status
BusyTime
Status 1
status
Published
线程池(Thread Pool)是一种基于池化技术的线程管理策略。
带着问题学习
- 线程池是什么?
- 线程池有几种?
- 为什么要用线程池?
- 线程池的组成是什么样的?
- 不同线程池之间有什么差别?
线程池简介
线程池的好处
- 提高资源利用率:通过重复使用已创建的线程,减少了线程创建和销毁的开销。
- 提高响应速度:当任务到达时,任务可以不需要等待线程创建就立即执行,因为线程池中已有线程准备好接收任务。
- 统一的资源管理和调度:线程池允许系统通过统一的方式来管理线程,避免了对线程的无限制创建。
- 提供更多的管理策略:线程池提供了如设置最大并发数、选择合适的队列策略、设置线程存活时间等多种管理策略。
线程池相关参数
线程池的工作流程

线程池接口及定义
Executor 接口
Executor是最基本的线程池接口,Executor接口非常简单,只有一个execute(Runnable command)方法,用于提交执行任务。ExecutorService 接口
ExecutorService 是 Executor 接口的一个子接口,定义了线程池的基本方法,所有的线程池都应该实现这个接口任务提交
submit(Callable<T> task)
submit(Runnable task)
submit(Runnable task, T result)
执行多个任务
invokeAll(Collection<? extends Callable<T>> tasks): 执行给定的任务集合,当所有任务完成时,返回保持任务状态和结果的Future列表。
invokeAny(Collection<? extends Callable<T>> tasks): 执行给定的任务集合,如果最早完成的任务正常终止,则返回其结果。
管理线程池的生命周期
shutdown(): 启动一个有序的关闭过程,不再接受新任务,同时等待已提交的任务执行完成。
shutdownNow(): 尝试停止所有任务,停止处理正在等待的任务,并返回等待执行的任务列表。(正在执行的任务,没有主动停止的情况下,不会被停止)
isShutdown(): 检查线程池是否已经关闭。
isTerminated(): 检查关闭后是否所有任务都已完成。
ThreadPoolExecutor类
ThreadPoolExecutor是ExecutorService接口的一个具体实现。
- 通过传入不同的参数给
ThreadPoolExecutor构造函数,可以详细地自定义线程池的行为。
- 构造函数的参数包括:
corePoolSize:核心线程数,即使空闲,线程池中也会保留在池中的线程数。maximumPoolSize:线程池中允许的最大线程数。keepAliveTime:当线程数大于核心线程数时,这是超过该时间的多余空闲线程在终止前等待新任务的最长时间。unit:keepAliveTime参数的时间单位。workQueue:用于在执行任务之前保存任务的队列。这可以是一个有界队列也可以是无界队列,依赖于具体的需求。threadFactory:用于创建新线程的工厂。handler:当线程池已满且无法接受新任务时的拒绝策略。
Executors
Executors是一个工厂类,提供了多种静态方法来创建不同类型的线程池。
- 相关的创建方法有:
newFixedThreadPool(int nThreads)newCachedThreadPool()newSingleThreadExecutor()newScheduledThreadPool(int corePoolSize)newSingleThreadScheduledExecutor()newWorkStealingPool()unconfigurableExecutorService(ExecutorService executor)unconfigurableScheduledExecutorService(ScheduledExecutorService executor)
线程池分类
线程池类型 | 核心参数 | 队列类型 | 线程数量变化 | 使用场景 | 特点 |
FixedThreadPool | 固定线程数量 | LinkedBlockingQueue | 固定线程数 | 适用于处理任务数量和资源消耗相对稳定的场景 | 避免频繁创建/销毁线程,提高资源利用率 |
CachedThreadPool | 线程数不固定,空闲线程60秒后终止 | SynchronousQueue | 根据任务增减 | 适合执行大量短期异步任务 | 线程数灵活,空闲时释放资源 |
SingleThreadExecutor | 单线程执行任务 | LinkedBlockingQueue | 单一线程,不变 | 需要保证任务顺序执行,如串行化操作 | 避免多线程同时执行的数据不一致性问题 |
ScheduledThreadPool | 固定线程数量,支持延迟/周期性任务 | DelayedWorkQueue | 核心线程数固定,非核心线程数可灵活调整(默认无非核心线程) | 适用于需要多个后台线程执行周期性任务,保持执行频率或具有延迟的任务 | 定时或周期性执行任务 |
ThreadPoolExecutor重要参数
任务队列
队列类型 | 特点 | 使用场景 | 注意事项 |
SynchronousQueue | 不存储元素,因此提交到线程池的任务必须立即执行,否则会在新线程中执行或被拒绝。 | 适用于任务传递,确保任务被立即执行 | 高线程创建率,可能导致性能问题 |
LinkedBlockingQueue | 阻塞队列,基于链表,通常配置为无界,也可设定界限 | 适合任务执行速度慢或提交频率高的场景 | 无界队列可能导致内存耗尽 |
ArrayBlockingQueue | 基于数组的有界阻塞队列 | 需要限制排队任务数量以避免资源过度使用的场景 | 需合理设定容量,以平衡内存使用和系统响应能力 |
PriorityBlockingQueue | 支持优先级排序的无界阻塞队列 | 需要根据任务紧急程度或重要性动态处理任务的场景 | 任务必须实现 Comparable接口,定义优先级比较规则,无界设置可能导致资源耗尽 |
DelayedWorkQueue | 用于存放实现了 Delayed接口的元素,只有在延迟期满时才能取走 | 执行延时或定时任务 | 管理延时任务时要确保时间的准确性和效率 |
拒绝策略
拒绝策略 | 特点 | 使用场景 | 注意事项 | 默认使用此策略的线程池 |
AbortPolicy | 抛出 RejectedExecutionException异常 | 任务不能延迟执行且必须处理拒绝情况时使用 | 需要适当处理异常,避免程序崩溃 | CachedThreadPool, ScheduledThreadPool |
CallerRunsPolicy | 调用者线程自己执行任务 | 调用者可以承受任务执行的延迟 | 可能导致调用者线程性能下降 | 无默认使用 |
DiscardPolicy | 静默丢弃任务 | 可以容忍丢失任务的场景 | 任务可能不被执行,无异常抛出 | 无默认使用 |
DiscardOldestPolicy | 丢弃队列中最老的任务,尝试提交当前任务 | 优先处理新任务,旧任务不是关键性的情况 | 可能导致重要任务丢失,需评估业务对任务的重要性 | 无默认使用 |
线程池的状态管理
ThreadPoolExecutor类使用一个int类型的变量来维护线程池的状态和工作线程的数量,这一变量被设计为包含两部分信息:高位表示线程池的状态,低位表示有效线程的数量。线程池状态
- RUNNING: 线程池可以接受新任务,也可以处理阻塞队列中的任务。
- SHUTDOWN: 线程池不接受新任务,但可以处理已添加的任务。
- STOP: 线程池不接受新任务,不处理队列中的任务,还会尝试中断正在处理的任务。
- TIDYING: 所有任务都已终止,
workerCount(有效线程数)为零,线程池的状态将转变为TIDYING。当线程池变为TIDYING状态时,将会执行terminated()方法。
- TERMINATED:
terminated()方法已完成。
状态转换
execute()方法在提交新任务时检查线程池状态,只有当状态为RUNNING时才会接受新任务。
shutdown()方法使线程池状态变为SHUTDOWN。调用此方法后,线程池将不再接受新任务,但会继续处理已在队列中的任务。
shutdownNow()方法尝试立即停止所有正在执行的任务,并将状态设为STOP,并尝试中断所有正在执行的线程。
- 状态从
TIDYING转换到TERMINATED发生在terminated()方法执行完毕之后。
关闭线程池的方法
关闭方法 | 特点 | 适用场景 | 注意事项 |
shutdown() | 停止接受新任务,已提交的任务继续执行。 | 希望所有已提交的任务完成时使用。 | - 不会立即终止执行中的任务。
- 通常用于应用程序正常结束时。 |
shutdownNow() | 尝试停止所有正在执行的任务,返回未开始执行的任务列表。 | 需要立即停止所有任务,包括正在执行的任务。 | - 可能无法立即停止所有任务。
- 返回列表中的任务未执行。 |
awaitTermination() | 阻塞当前线程,直到线程池完全终止或超时,或线程被中断。 | 在调用 shutdown()或shutdownNow()后,等待线程池完全关闭。 | - 需要处理 InterruptedException。
- 确保在超时后检查线程池是否已完全终止。 |
注意事项
- 在关闭线程池后提交任务会导致
RejectedExecutionException。
shutdownNow()可能无法立即停止所有正在执行的任务,因为某些任务可能不响应中断。
- 在调用
awaitTermination()后,应处理InterruptedException,以确保当前线程在等待过程中被中断后可以正确响应。
- 确保在应用程序关闭或重新启动前,线程池被正确关闭,以避免资源泄露。
- Author:CoderWdd
- URL:https://www.wuinsights.top//article/01HWA0YK3E0KZKS5514MN0J9GG
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!