#TOC
线程池 复习(预习)
什么是线程池?
线程池是管理了一组工作线程,同时它还包括了一个用于防止等待任务队列的任务队列(阻塞队列)。
线程池体系
从左到右 → 分别表示了线程池的 接口、类继承关系
接口 | 接口 | 抽象类 | 实现类 |
---|---|---|---|
Executor | ExecutorService | AbstractExecutorService | ThreadPoolExecutor |
Executors : 类包含了建立 ThreadPool的几种静态方法,可以类比于Arrays和Collections等
Executors 类:
Executors.newSingleThread(); 单个线程
Executors.newFixedThreadPool(); 固定数量线程
Executors.newCachedThreadPool(); 大小无限(取决于操作系统或者JVM的最大线程)
Executors.newScheduledThreadPool(); 大小无限(可以指定大小),支持周期性和定义的任务执行
线程池的参数
- corePoolSize : 核心线程数
- maximumPoolSize: 最大线程数
- keepAliveTime: 空闲线程最大存活时间
- Unit: 存活时间单位
- workQueue: 工作队列(阻塞队列)
- threadFactory:线程工程类:产生新的线程
- handler: 处理线程池满的处理器
workQueue的具体实现类
- ArrayBlockingQueue : 基于数组的FIFO队列,创建时必须制定大小
- LinkedBlockingQueue:基于链表的FIFO队列,可以指定大小,默认为Integer.MAX_VALUE
- synchronousQueue:不保存提交的任务,而是新建线程来执行新任务。只有等其他线程取走当前任务时,才能添加新任务
三种队列从上到下,吞吐量增加。
线程池执行流程
- 新建线程池,此时线程池内线程数量为0,(可以调用preStartThread或者preStartAllThread来提前初始化)
- 当有任务提交给线程池时,如果此时任务的数量小于corePoolSize,则生成一个新的线程来处理这个任务(不管此时是否有线程空闲)
- 当线程池中运行的线程的数量已经达到corePoolSize时,此时,缓存队列workQueue 开始发挥作用了,此时有两种情况:
- 当缓存队列未满:
任务加入缓存队列 - 当缓存队列满:
- 此时当任务数量小于maximumPoolSize时,线程池会新建线程来运行当前 线程。
- 当任务数量已经大于maximumPoolSize时,线程池就会调用RejectExecutionHandler来处理异常。下面在介绍参数handler时会进行介绍
- 当缓存队列未满:
- 注意处于corePoolSize和maximumPoolSize之间的线程,会被自动释放,当线程数超过corePoolSize后,如果某个线程超过了KeepAliveTime,他就会被终止,直到线程数不大于corePoolSize,这就完成了线程数量的动态调整。
handler 4种线程池满处理机制
- AbortPolicy : 直接抛出异常
- DiscardPolicy : 丢弃当前任务
- DiscardOldestPolicy : 丢弃最旧的任务(队列头),并执行当前任务。
- CallerRunsPolicy:调用者线程执行当前任务
典型线程池结构
- 线程管理器 : 用于启动、停用和管理线程池
- 工作线程:线程池中的线程
- 请求接口: 创建请求对象,以供工作线程调度任务的执行
- 请求队列: 用于存放和提取请求
- 结果队列: 用于存储返回结果
线程池的5种状态
- Running: 能过接受新任务,对新任务做处理
- Shutdown: 处于shutdown状态,不接受新任务,但是可以处理已处理任务
- Stop: 不接受新任务,不处理已添加任务,并且中断正在进行的任务
- Tidying: 当所有任务已终止,线程池的状态会变成Tidying,之后会执行钩子函数terminated();
- Terminated: 线程池彻底结束
相关函数
- shutdown: 关闭线程池,不接受新任务,处理完当前已存在的任务后结束
- shutdownNow: 关闭线程池,不接受新任务,中断当前正在处理的任务,返回还未处理的任务
其他函数:
submit(): 有返回值,方便异常处理,可以通过Future.get抛出异常
execute(): 无返回值
参考:
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ThreadPoolExecutor.html
https://www.baeldung.com/thread-pool-java-and-guava