前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自定义线程池理论知识部分

自定义线程池理论知识部分

作者头像
关忆北.
发布2021-12-07 16:42:56
5710
发布2021-12-07 16:42:56
举报
文章被收录于专栏:关忆北.关忆北.关忆北.
一、线程池是什么

线程池是一种基于池化思想管理线程的工具。

创建/销毁是一个耗时操作,频繁使用会降低整体性能,使用线程池维护多个线程,可有效降低运行中性能开销,以及更好的管理线程。

Java中自定义线程池是自JDK1.5后出现的ThreadPoolExecutor。 Executor提供了一种思想:将任务提交和任务执行进行解耦,在编码时只需将要执行耗时操作逻辑放入Runanble中即可,无需关心线程调度和执行。

在这里插入图片描述
在这里插入图片描述

ExecutorService提供了扩充执行任务的能力,在执行线程内操作时可以获取执行后的返回值Future,同时提供了线程池管控能力。

图2 ThreadPoolExecutor运行流程
图2 ThreadPoolExecutor运行流程

线程池内部实际上构建了一个生产者、消费者模型,将线程和任务解耦,并不直接关联,从而复用线程。

线程池的组成
  1. 任务管理:(生产者角色)
  2. 线程管理:(消费者角色)

当提交任务后所经步骤:

  1. 直接申请线程执行该任务
  2. 缓冲到队列中等待线程执行
  3. 拒绝该任务

线程被统一维护在线程池内,根据任务请求进行线程分配,当线程执行完任务后会继续获取新任务执行,最终当线程获取不到任务的时候,线程就会被回收。

线程池生命周期
ThreadPoolExecutor几个重要参数:

corePoolSize:线程池的基本大小,即在没有任务需要执行的时候线程池的大小,并且只有在工作队列满了的情况下才会创建超出这个数量的线程。

maximumPoolSize:线程池中允许的最大线程数,线程池中的当前线程数不会超过该值。

线程池生命周期是由内部隐式维护,线程池的运行状态(runState)和有效线程数量(workerCount)关乎线程池的运行状态。

poolSize:线程池中当前线程的数量,其值为0的时候,意味着没有任何线程,线程池终止。

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

主池控制状态ctl是一个原子整数,封装了两个概念字段workerCount:表示有效线程数runState:表示是否正在运行、正在关闭等,高3位保存runState,低29位保存workerCount

runState 提供主要的生命周期控制,取值:

  • RUNNING:接受新任务并处理排队任务
  • SHUTDOWN:关闭状态,不接受新任务,但处理排队任务
  • STOP:不接受新任务,不处理排队任务,并中断正在进行的任务
  • TIDYING:所有任务都已终止
  • TERMINATED:terminate() 已完成

当workerCount 为零时,转换到状态 TIDYING 的线程将运行 terminate() 钩子方法。

private static int runStateOf(int c)     { return c & ~CAPACITY; } //计算当前运行状态
private static int workerCountOf(int c)  { return c & CAPACITY; }  //计算当前线程数量
private static int ctlOf(int rs, int wc) { return rs | wc; }   //通过状态和线程数生成ctl

runState 随时间递增,但不需要命中每个状态。 转换是: RUNNING -> SHUTDOWN 在调用 shutdown() 时,可能隐含在 finalize() 中(RUNNING 或 SHUTDOWN)-> STOP 在调用 shutdownNow() 时 SHUTDOWN -> TIDYING 当队列和池都为空时 STOP -> TIDYING当池为空时 TIDYING -> TERMINATED 当 terminate() 钩子方法完成时,在 awaitTermination() 中等待的线程将在状态达到 TERMINATED 时返回。 检测从 SHUTDOWN 到 TIDYING 的转换,因为在非空之后队列可能会变空,在 SHUTDOWN 状态期间反之亦然,但是我们只能在看到它为空后看到 workerCount 时才终止是 0

生命周期流程

图3 线程池生命周期
图3 线程池生命周期
任务执行机制

任务调度是线程池的主要入口,用户提交了一个任务,如何执行任务都是由这个阶段决定的。

所有任务的调度都是由execute()方法完成的。

执行流程:

执行流程需要完成的任务:检查现在线程池的运行状态、运行线程数、运行策略、申请线程运行/缓冲到队列/拒绝该任务。

  1. 检测线程池运行状态,如果不是RUNNING,则直接拒绝
  2. workerCount < corePoolSize,创建并启动一个线程来执行新提交的任务
  3. workerCount >= corePoolSize且线程池内的阻塞队列未满,则将任务添加到阻塞队列中,等候处理workQueue.offer(command);
  4. workerCount >= corePoolSize && workerCount < maximumPoolSize && 线程池内的阻塞队列已满,则创建并启动一个线程来执行新提交的任务
  5. workerCount >= maximumPoolSize,并且线程池内的阻塞队列已满,则根据拒绝策略处理该任务,默认处理的方式是直接了抛出异常。
图4 任务调度流程
图4 任务调度流程
任务缓冲

任务缓冲模块是线程池能够管理任务的核心部分,线程池的本质是对任务和线程的管理,而做到这一点最关键的思想就是将任务和线程两者解耦,不让两者直接关联,才可以做后续的分配工作。线程池中是以生产者消费者模式,通过一个阻塞队列来实现的。阻塞队列缓存任务,工作线程从阻塞队列中获取任务。

任务申请

两种情况

  1. 直接由新创建的线程执行
  2. 线程从任务队列中获取任务然后执行,执行完任务的线程会再次去队列中申请任务再去执行。
图6 获取任务流程图
图6 获取任务流程图
任务拒绝

作用是保护线程池,任务队列已满、线程池中的线程数据达到maximumPoolSize时(线程池最大容量)会使用拒绝策略。

public interface RejectedExecutionHandler {
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
img
img
Worker线程管理

线程池使用工作线程Worker维护线程的生命周期。Worker实现了Runnable接口,并持有一个线程thread,一个初始化的任务firstTask。

Worker线程增加

增加线程是通过线程池的addWorker方法,该方法不考虑在哪个阶段增加的该线程,其功能仅仅是是增加一个线程,并返回是否成功。

图9 申请线程执行流程图
图9 申请线程执行流程图
Worker线程回收

线程池中的销毁依赖JVM的自动回收,线程池根据当前状态维护一定数量的线程引用,防止被JVM回收,当决定回收时,将其引用消除即可,Worker被创建后会不断轮询,核心线程可以无限等待获取任务,非核心线程即时获取任务,Worker无法获取到任务,循环结束,Worker主动消除线程池种的引用。

try {
  while (task != null || (task = getTask()) != null) {
    //执行任务
  }
} finally {
  processWorkerExit(w, completedAbruptly);//获取不到任务时,主动回收自己
}
图10 线程销毁流程
图10 线程销毁流程
Worker线程执行任务

Worker类中的run方法调用了runWorker方法来执行任务。

1.while循环不断地通过getTask()方法获取任务。 2.getTask()方法从阻塞队列中取任务。 3.如果线程池正在停止,那么要保证当前线程是中断状态,否则要保证当前线程不是中断状态。 4.执行任务。 5.如果getTask结果为null则跳出循环,执行processWorkerExit()方法,销毁线程。

图11 执行任务流程
图11 执行任务流程
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-06-06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、线程池是什么
  • 线程池的组成
  • 线程池生命周期
    • ThreadPoolExecutor几个重要参数:
    • 任务执行机制
      • 执行流程:
      • 任务缓冲
      • 任务申请
      • 任务拒绝
      • Worker线程管理
        • Worker线程增加
          • Worker线程回收
            • Worker线程执行任务
            相关产品与服务
            NAT 网关
            NAT 网关(NAT Gateway)提供 IP 地址转换服务,为腾讯云内资源提供高性能的 Internet 访问服务。通过 NAT 网关,在腾讯云上的资源可以更安全的访问 Internet,保护私有网络信息不直接暴露公网;您也可以通过 NAT 网关实现海量的公网访问,最大支持1000万以上的并发连接数;NAT 网关还支持 IP 级流量管控,可实时查看流量数据,帮助您快速定位异常流量,排查网络故障。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档