线程池的五种状态
                           
天天向上
发布: 2025-04-26 19:19:37

原创
157 人浏览过

ThreadPoolExecutor 里面,线程池有 5 种状态,用 ctl 的高位(29位) 表示。
状态是按生命周期严格有序变化的!


一、线程池的五种状态

1. RUNNING(运行中)

  • 定义:能接受新任务,同时也能处理队列中的任务。
  • 特点
    • execute() 提交任务 ➔ 正常处理。
    • 核心状态。
  • 标志值
    • RUNNING = -1 << COUNT_BITS
    • 即高位全是 1(负数)。

2. SHUTDOWN(优雅关闭)

  • 定义:不再接收新任务,但继续执行已提交(在队列中的)任务。
  • 特点
    • 调用 shutdown()
    • 线程池不新建线程,只处理已有任务。
    • 任务处理完后,自动进入下一个状态。
  • 标志值
    • SHUTDOWN = 0 << COUNT_BITS

3. STOP(暴力关闭)

  • 定义:不接收新任务,也不处理队列中的任务,中断正在执行的线程
  • 特点
    • 调用 shutdownNow()
    • 直接打断所有线程,清空工作队列。
  • 标志值
    • STOP = 1 << COUNT_BITS

4. TIDYING(整理阶段)

  • 定义:所有任务都结束(线程数为0,队列为空)后,进入清理阶段。
  • 特点
    • 触发钩子方法 terminated()
  • 标志值
    • TIDYING = 2 << COUNT_BITS

5. TERMINATED(终结状态)

  • 定义terminated() 方法执行完成后,线程池彻底终结。
  • 特点
    • 彻底关闭,生命周期结束。
  • 标志值
    • TERMINATED = 3 << COUNT_BITS

二、五种状态的完整变化流程图

RUNNING 
   ↓ shutdown()
SHUTDOWN 
   ↓ 任务处理完毕
TIDYING
   ↓ terminated()
TERMINATED

或者异常暴力关闭:

RUNNING 
   ↓ shutdownNow()
STOP 
   ↓ 任务全部终结
TIDYING
   ↓ terminated()
TERMINATED

三、四种拒绝策略(RejectedExecutionHandler)


当线程池无法处理新任务时(比如:线程池满了 + 队列满了),就调用拒绝策略。
JDK 提供了 4 种标准实现,每一种都非常重要,面试爱问!


1. AbortPolicy(默认)

  • 行为
    • 直接抛出 RejectedExecutionException
  • 特点
    • 不默默丢弃,立即失败报警
  • 适用场景
    • 重要业务,任务必须保证提交成功,否则立刻报错。

2. CallerRunsPolicy

  • 行为
    • 谁提交的任务,谁自己执行(在调用 execute 的线程里同步跑)。
  • 特点
    • 降低线程池压力,保护系统。
    • 可能会让提交线程变慢,从而降低总系统压力。
  • 适用场景
    • 可以接受降级处理的场景,比如后台日志系统。

3. DiscardPolicy

  • 行为
    • 直接丢弃任务,不抛异常。
  • 特点
    • 悄无声息地丢掉,业务无感知。
  • 适用场景
    • 对任务可靠性要求不高,比如定时上报小数据。

4. DiscardOldestPolicy

  • 行为
    • 丢掉工作队列里最老的任务,然后重新提交新任务。
  • 特点
    • 保证新任务尽量进来,牺牲旧任务。
  • 适用场景
    • 优先处理最新、最重要任务,比如流式消息处理。

【拒绝策略总结一句话版】

“抛异常(Abort) ➔ 自己跑(CallerRuns) ➔ 直接丢(Discard) ➔ 丢旧换新(DiscardOldest)”


拓展加分(如果想冲面试官印象的话)

可以加一句:

“实际生产中,很多团队会自定义 RejectedExecutionHandler,比如加日志报警、监控指标上报、队列持久化重试等方式,提升系统的可观测性与可靠性。”


更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *