学习【线程池】原理知识这一篇就够了

线程池原理知识

1. 线程池基础

线程池是什么

线程池概念:

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

线程池好处:

  • 如果没有线程池,线程过多会带来额外的开销,例如:创建销毁线程的开销、调度线程的开销
  • 线程池负责维护多个线程,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题。
  • 线程池好处包括:
    1. 降低资源消耗:通过池化技术重复利用已创建的线程,降低线程创建和销毁造成的损耗。
    2. 提高响应速度:任务到达时,无需等待线程创建即可立即执行。
    3. 提高线程的可管理性: 线程是稀缺资源,如果无限制创建,不仅会消耗系统资源,还会因为线程的不合理分布导致资源调度失衡,降低系统的稳定性。使用线程池可以进行统一的分配、监控。

线程池解决了什么问题

线程池解决的核心问题就是资源管理问题。在并发环境下,系统不能够确定在任意时刻,有多少任务需要执行,有多少资源需要投入。这种不确定性会降低系统的稳定性。

为了解决资源分配问题,线程池采用了池化的思想。就是将资源统一在一起管理的思想。

2. 线程池核心设计与实现

总体设计

在这里插入图片描述

ThreadPoolExecutor一方面维护自身的生命周期,另一方面管理线程和任务,使两者良好的结合从而执行并行任务。

生命周期管理

ThreadPoolExecutor的运行状态有5种,分别为

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

任务执行机制

1. 任务调度

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

任务调度的执行过程:

  1. 首先检测线程池运行状态,如果不是RUNNING,则直接拒绝,线程池要保证在RUNNING的状态下执行任务。
  2. 如果workerCount < corePoolSize,则创建并启动⼀个线程来执行新提交的任务。
  3. 如果workerCount >= corePoolSize,且线程池内的阻塞队列未满,则将任务添加到该阻塞队列中。
  4. 如果workerCount >= corePoolSize && workerCount < maximumPoolSize,且线程池内的阻塞队列已满,则创建并启动⼀个线程来执行新提交的任务。
  5. 如果workerCount >= maximumPoolSize,并且线程池内的阻塞队列已满,则根据拒绝策略来处理该任务,默认的处理方式是直接抛异常。

在这里插入图片描述

2. 任务缓冲

线程池中是以生产者消费者模式,通过一个阻塞队列来实现的。阻塞队列缓存任务,工作线程从阻塞队列中获取任务。

在这里插入图片描述

3. 任务申请

任务申请有2种:

  1. 任务直接由新创建的线程执行,无需调用 getTask() 获取任务。
  2. 任务先被放到任务队列,然后再由空闲线程申请,此时线程需要调用 getTask() 申请任务。

getTask() 申请任务流程图

在这里插入图片描述

4. 任务拒绝

当线程池的任务缓存队列已满,并且线程池中的线程数目达到 maximumPoolSize 时,就需要拒绝掉该任务,采取任务拒绝策略,保护线程池。

拒绝策略是⼀个接口,其设计如下:

public interface RejectedExecutionHandler {
 	void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

⽤户可以通过实现这个接口去定制拒绝策略,也可以选择JDK提供的四种已有拒绝策略,其特点如下:

在这里插入图片描述

Worker线程管理

Worker线程

Worker线程增加

Worker线程回收

Worker线程执行任务

3. 线程池在业务中的实践

业务背景

场景一:快速响应用户请求

用户的发起的实时请求,往往需要多个调用,之后要将所有的数据聚合起来返回给用户。

为了追求响应时间,可以使用线程池将调用封装成任务并行的执行,缩短总体响应时间

在这里插入图片描述

场景二:快速处理批量任务

这种场景需要执行大量的任务,并不要求瞬时完成,而是关注在单位时间内,尽可能的处理更多的任务。

可以使用线程池,并行执行任务,提高吞吐量。

实际问题及方案思考

4. 动态化线程池设计方案

动态化线程池:

  • 将线程池的参数从代码中迁移到分布式配置中心上,实现线程池参数可动态配置和即时生效,线程池参数动态化前后的参数修改流程对比如下:

在这里插入图片描述

动态化线程池整体设计:

在这里插入图片描述

动态修改配置

线程池构造参数有8个,但是最核心的是3个:corePoolSizemaximumPoolSizeworkQueue

所以线程池只需要提供这三个关键参数的配置即可。

线程池信息监控

动态化线程池考虑了多个维度的监控。如:线程池活跃度、任务的执行Transaction(频率、耗时)、Reject异常、线程池内部统计信息等。

这些监控信息既能从多个维度分析线程池的使用情况,又能在出现问题第一时间通知到用户,从而避免故障或加速故障恢复。

线程池告警通知

可以从两方面来看线程池的过载判定条件。

  1. 发生了 Reject 异常
  2. 任务队列中的等待任务超过指定的阈值、

以上两种情况发生了都会触发告警,告警信息会通过邮件发送给负责人。

参考文章:

Java线程池实现原理及其在美团业务中的实践

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值