面试题答案
一键面试线程池饱和时系统行为表现
- 使用AbortPolicy拒绝策略:
- 当线程池饱和,即线程池中的线程数达到最大线程数且工作队列LinkedBlockingQueue也已满时,新提交的任务会被AbortPolicy拒绝。此时,它会抛出
RejectedExecutionException
异常,阻止任务的进一步提交。
- 当线程池饱和,即线程池中的线程数达到最大线程数且工作队列LinkedBlockingQueue也已满时,新提交的任务会被AbortPolicy拒绝。此时,它会抛出
- 使用CallerRunsPolicy拒绝策略:
- 当线程池饱和时,新提交的任务不会被直接拒绝,而是由提交任务的线程来执行该任务。这意味着提交任务的线程会暂时放弃自身的工作,去执行这个新任务,执行完成后再继续自己的工作。这样可以减轻线程池的压力,因为不会有新任务持续进入工作队列,同时也不会抛弃任务。
可能存在的风险
- 内存占用风险(LinkedBlockingQueue无界特性):
- 由于LinkedBlockingQueue是无界队列,理论上可以不断添加任务。在高并发情况下,如果任务提交速度持续高于任务处理速度,队列会不断增长,可能导致内存占用不断上升,最终引发
OutOfMemoryError
,使系统崩溃。
- 由于LinkedBlockingQueue是无界队列,理论上可以不断添加任务。在高并发情况下,如果任务提交速度持续高于任务处理速度,队列会不断增长,可能导致内存占用不断上升,最终引发
- 响应延迟风险:
- 当使用CallerRunsPolicy时,提交任务的线程需要执行任务,这会导致提交线程自身的响应延迟。如果提交线程是处理用户请求等对响应时间敏感的线程,会严重影响用户体验。
应对措施
- 限制队列大小:
- 可以将LinkedBlockingQueue改为有界队列,例如
LinkedBlockingQueue(int capacity)
,这样当队列满时,任务就无法再进入队列,避免无限制的内存增长。
- 可以将LinkedBlockingQueue改为有界队列,例如
- 调整线程池参数:
- 根据系统的负载和任务特性,合理调整线程池的核心线程数、最大线程数等参数,使线程池能够更有效地处理任务,减少任务堆积的情况。例如,如果任务处理时间较长,可以适当增加线程数。
- 监控与预警:
- 对线程池的状态(如队列大小、活跃线程数等)进行监控,设置合理的阈值。当达到阈值时,通过监控系统发出预警,以便及时调整系统配置或排查性能瓶颈。
- 优雅降级:
- 对于非关键任务,可以在系统负载过高时,采用适当的降级策略,如直接丢弃任务并记录日志,保证关键任务的正常执行。