MST
星途 面试题库

面试题:Java线程池饱和策略在高并发场景下的应用优化

假设在一个高并发的电商秒杀系统中,使用Java线程池处理订单业务,当线程池达到饱和时,如何结合不同的饱和策略进行优化,以确保系统稳定运行且尽可能处理更多的请求?请详细阐述你的思路和方案。
45.0万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试
  1. AbortPolicy(默认策略)
    • 思路:当线程池饱和时,直接抛出RejectedExecutionException异常。这种策略适用于希望在系统无法处理任务时快速失败并进行错误处理的场景。
    • 方案:在调用线程池的executesubmit方法时,使用try - catch块捕获RejectedExecutionException异常。在catch块中,可以记录详细的日志信息,包括当前系统的负载情况(如活动线程数、队列大小等),然后根据业务需求决定是向用户返回提示信息(如“秒杀人数过多,请稍后重试”),还是采取其他应急措施,如将该订单请求放入一个临时的持久化队列(如基于文件或数据库的队列),后续由专门的线程或服务进行处理。
  2. CallerRunsPolicy
    • 思路:当线程池饱和时,将被拒绝的任务返回给调用者线程来执行。这样可以减轻线程池的压力,利用调用者线程的资源来处理任务。
    • 方案:在电商秒杀场景中,调用者线程通常是处理用户请求的Web容器线程。采用这种策略时,需要考虑到调用者线程处理任务可能会影响其处理其他请求的性能。可以通过设置一个计数器,记录由调用者线程处理的任务数量。当这个数量达到一定阈值时,开始对后续请求进行限流处理,比如返回“当前请求过多,请稍后重试”的提示信息。同时,在调用者线程处理任务时,可以对任务执行时间进行监控,如果发现任务执行时间过长,同样可以采取限流措施。
  3. DiscardPolicy
    • 思路:当线程池饱和时,直接丢弃被拒绝的任务,不做任何处理。这种策略适用于对任务丢失不太敏感,且希望快速处理高并发请求的场景。
    • 方案:在使用这种策略时,需要在业务层面进行一些补偿机制。例如,记录被丢弃的订单请求相关信息(如用户ID、商品ID等)到日志或数据库中。然后,启动一个定时任务,定期检查这些被丢弃的请求记录。如果发现某个商品还有库存且该订单请求在一定时间内(如1分钟)被丢弃,可以尝试重新发起该订单请求,将其重新提交到线程池或者放入一个优先级较高的队列中等待处理。
  4. DiscardOldestPolicy
    • 思路:当线程池饱和时,丢弃队列中最老的任务,然后尝试将新任务加入队列。
    • 方案:在电商秒杀系统中,需要谨慎使用这种策略。因为丢弃老的订单请求可能会导致部分用户等待时间过长后反而失去购买机会。可以在丢弃老任务时,对老任务进行标记,记录其丢弃原因和相关信息。同时,对于被丢弃老任务对应的用户,可以发送通知(如短信或站内信)告知其订单可能由于高并发原因未及时处理,给予一定的补偿(如优惠券)。另外,可以对队列中的任务设置优先级,优先丢弃优先级较低的任务,对于秒杀热门商品的订单任务可以设置较高优先级,尽量避免被丢弃。