面试题答案
一键面试设计动态调整核心线程数的Java线程池
- 调整策略:
- 基于任务队列长度:当任务队列长度超过某个阈值(例如队列容量的75%)时,增加核心线程数;当任务队列长度低于某个阈值(例如队列容量的25%)且当前核心线程数大于初始核心线程数时,减少核心线程数。
- 基于系统负载:通过获取系统的CPU利用率、内存使用率等指标来动态调整核心线程数。例如,当CPU利用率持续超过80%,且任务队列不为空时,增加核心线程数;当CPU利用率持续低于20%,且有空闲核心线程时,减少核心线程数。
- 涉及的参数:
- 核心线程数(corePoolSize):线程池维护的最小线程数。
- 最大线程数(maximumPoolSize):线程池能够创建的最大线程数。
- 队列容量(capacity):任务队列的容量大小。
- 线程存活时间(keepAliveTime):当线程数大于核心线程数时,多余的空闲线程的存活时间。
- 拒绝策略(RejectedExecutionHandler):当任务无法提交到队列且线程池达到最大线程数时,如何处理新任务。常见的有AbortPolicy(抛出异常)、CallerRunsPolicy(在调用者线程中执行任务)、DiscardPolicy(丢弃任务)、DiscardOldestPolicy(丢弃队列中最老的任务)。
- 不同业务场景下策略的合理性:
- I/O密集型业务:
- 合理性:I/O操作等待时间长,线程大部分时间处于等待状态,增加核心线程数可以充分利用系统资源,提高任务处理效率。基于任务队列长度的策略能及时响应任务堆积,基于系统负载的策略可避免过度创建线程导致系统资源耗尽。
- 潜在问题:如果核心线程数增加过多,可能会导致线程上下文切换开销增大,降低系统性能。同时,若线程存活时间设置不合理,可能会频繁创建和销毁线程,也增加开销。
- CPU密集型业务:
- 合理性:CPU密集型任务需要大量的CPU计算资源,基于系统负载动态调整核心线程数能避免过多线程竞争CPU资源,保证系统性能。当CPU利用率高时增加线程数,可充分利用多核CPU优势;利用率低时减少线程数,避免资源浪费。
- 潜在问题:若调整不及时,可能会导致任务处理延迟。例如,在任务突发增加时,未能及时增加核心线程数,会使任务在队列中积压,响应时间变长。
- I/O密集型业务:
在实现动态调整核心线程数的线程池时,需要综合考虑系统的业务特性、资源状况等因素,合理设置参数和调整策略,以达到最优的性能和资源利用率。