# 《Seckill秒杀系统》第84章:基于线程池实现单机并发数限流

作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)

沉淀,成长,突破,帮助他人,成就自我。

  • 本章难度:★★☆☆☆
  • 本章重点:理解线程池限流的原理,从源码级别重点掌握基于线程池实现并发数限流的核心技术与落地方案,并能够将其灵活应用到自身实际项目中。

大家好,我是冰河~~

在秒杀系统中,只存在分布式限流是远远不够的,我们还需要实现单机限流,单机限流不仅仅可以作为分布式限流的有效补充,还能在分布式限流出现故障时,作为兜底限流措施,尽最大努力保证秒杀系统的稳定性。

# 一、前言

在前面的文章中,我们基于QPS实现了单机API限流,可以作为分布式限流的补充和兜底措施。在实现单机限流时,不仅仅只有基于QPS的单机API限流,还可以扩展出许多单机限流模式,例如,可以基于线程池实现单机并发数限流。

# 二、本章诉求

基于线程池实现单机并发数限流,一旦单机并发数超过一定的阈值(这个阈值通常是线程池最大并发数+队列长度),则根据对应的拒绝策略来达到限流的目的。

# 三、线程池核心流程

向线程池中提交任务时,线程池会根据具体情况以某种流程执行当前任务,本节,就简单介绍下线程池执行任务的核心流程。

# 3.1 执行任务的流程

ThreadPoolExecutor是Java线程池中最核心的类之一,它能够保证线程池按照正常的业务逻辑执行任务,并通过原子方式更新线程池每个阶段的状态。

ThreadPoolExecutor类中存在一个workers工作线程集合,用户可以向线程池中添加需要执行的任务,workers集合中的工作线程可以直接执行任务,或者从任务队列中获取任务后执行。ThreadPoolExecutor类中提供了整个线程池从创建到执行任务,再到消亡的整个流程方法。

线程池执行任务的核心流程可以简化成如图84-1所示。


由图84-1可以看出,当向线程池中提交任务时,线程池执行任务的流程如下所示。

(1)向线程池提交任务时,首先会判断线程池中的线程数是否已经达到corePoolSize,如果线程池中的线程数未达到corePoolSize,则直接创建新线程执行任务。否则,进入步骤(2)。

(2)判断线程池中的工作队列是否已满,如果线程池中的工作队列未满,则将任务添加到队列中等待执行。否则,进入步骤(3)。

(3)判断线程池中的线程数是否已经达到maximumPoolSize,如果线程池中的线程数未达到maximumPoolSize,则直接创建新线程执行任务。否则,进入步骤(4)。

(4)执行拒绝策略,在执行拒绝策略时,即可实现基于线程池的并发数限流。

# 3.2 拒绝策略

如果线程池中的workQueue阻塞队列满了,同时,线程池中的线程数已达到maximumPoolSize,并且没有空闲的线程,此时继续向线程池提交任务,就需要采取某种策略来拒绝任务的执行。

# 查看完整文章

加入冰河技术 (opens new window)知识星球,解锁完整技术文章与完整代码