MST
星途 面试题库

面试题:Java线程池的拒绝策略及应用场景

请列举Java线程池中的几种拒绝策略,并说明每种策略在实际应用场景中的合理性与适用性。同时,假设你正在开发一个高并发的订单处理系统,当线程池满且任务队列也满时,你会选择哪种拒绝策略,为什么?
41.8万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. AbortPolicy(中止策略)
    • 策略描述:当任务无法被执行时,直接抛出 RejectedExecutionException 异常。
    • 合理性与适用性
      • 合理性:能立即反馈任务提交失败的信息,提醒开发者任务处理出现异常情况,便于及时排查问题。
      • 适用性:适用于对任务执行成功率要求极高,不允许任务丢失的场景。例如,在一些关键的金融交易系统中,每一笔交易都至关重要,若交易任务无法执行,抛出异常能让系统及时处理,避免交易数据丢失造成的损失。
  2. CallerRunsPolicy(调用者运行策略)
    • 策略描述:当任务无法被线程池处理时,由提交任务的线程(调用者线程)来执行该任务。
    • 合理性与适用性
      • 合理性:不会丢弃任务,并且可以在一定程度上降低新任务的提交速度,因为调用者线程在执行任务期间,不会再快速提交新任务。
      • 适用性:适用于对任务处理实时性要求不高,且希望能减少新任务提交频率的场景。比如一些日志记录系统,任务处理不及时对系统整体功能影响不大,采用该策略能在一定程度上缓解线程池压力。
  3. DiscardPolicy(丢弃策略)
    • 策略描述:当任务无法被执行时,直接丢弃该任务,不做任何处理。
    • 合理性与适用性
      • 合理性:简单粗暴,在系统资源紧张且任务并非至关重要的情况下,能避免因处理不了任务而引发的异常。
      • 适用性:适用于一些对任务可靠性要求较低,且系统资源有限的场景。例如,在一个实时统计网站访问量的系统中,偶尔丢失几个统计任务,对整体统计结果影响较小,却能保证系统在高并发下的稳定运行。
  4. DiscardOldestPolicy(丢弃最旧策略)
    • 策略描述:当任务无法被执行时,丢弃任务队列中最旧的任务,然后尝试将新任务加入任务队列。
    • 合理性与适用性
      • 合理性:优先保证新任务有机会被处理,同时在一定程度上维持任务队列的大小,避免任务队列无限增长。
      • 适用性:适用于任务具有时效性,新任务比旧任务更重要的场景。例如在实时股票交易系统中,新的交易指令比旧的指令更有处理价值,丢弃旧指令能让新指令及时得到处理。

在开发高并发的订单处理系统时,当线程池满且任务队列也满时,选择 CallerRunsPolicy 策略较为合适。原因如下:订单处理系统对任务可靠性要求高,不能随意丢弃订单任务(DiscardPolicyDiscardOldestPolicy 不合适);抛出异常(AbortPolicy)可能导致订单处理流程中断,影响用户体验且不利于系统的健壮性。而 CallerRunsPolicy 可以保证订单任务不会丢失,虽然调用者线程执行任务会使新订单提交速度暂时降低,但能在一定程度上缓解线程池和任务队列的压力,并且订单最终都能得到处理,符合订单处理系统对可靠性和稳定性的要求。