面试题答案
一键面试可能导致队列积压的原因
- 线程池核心线程数过少:核心线程数不足以快速处理提交的任务,使得任务大量进入队列等待。
- 最大线程数限制不合理:最大线程数设置过小,即使核心线程忙不过来,也无法创建更多线程处理任务,导致任务积压在队列。
- 任务提交速度过快:任务提交的频率远远高于线程池处理任务的速度,导致队列来不及处理新提交的任务。
- 队列容量有限:如果设置的队列容量较小,而任务持续快速提交,很快队列就会被填满。
通过线程池参数调整避免队列积压
- 合理设置核心线程数:根据任务处理的平均耗时和任务提交频率,适当增加核心线程数,确保能及时处理部分任务,避免任务过早进入队列。例如,如果任务平均处理时间短且提交频率高,可以适当提高核心线程数。
- 优化最大线程数:根据系统资源(如CPU、内存等)情况,合理设置最大线程数。当核心线程数不足以处理任务时,允许创建更多线程来处理任务,减少队列压力。但注意最大线程数不能设置过大,否则会消耗过多系统资源。
- 设置合适的线程存活时间(keepAliveTime):对于非核心线程,当任务处理完后,在一定时间(keepAliveTime)内如果没有新任务,线程会被销毁。合理设置这个时间,既可以避免线程频繁创建销毁带来的开销,又能在任务量降低时及时释放资源。
通过队列类型选择避免队列积压
- 无界队列(如LinkedBlockingQueue):适用于任务处理速度相对稳定且任务提交量波动不大的场景。它可以容纳大量任务,但可能导致任务堆积过多占用大量内存。
- 有界队列(如ArrayBlockingQueue):可以限制队列的容量,防止任务无限堆积。当队列满时,可结合拒绝策略处理新任务。适用于对系统资源有限制,需要严格控制任务量的场景。
- 优先队列(如PriorityBlockingQueue):适用于任务有优先级的场景,优先处理优先级高的任务,减少高优先级任务在队列中的等待时间。
通过拒绝策略设置避免队列积压
- AbortPolicy(默认策略):当队列满且线程池达到最大线程数时,直接抛出RejectedExecutionException异常。适用于需要立即知道任务是否被拒绝的场景,应用程序可以捕获异常并做出相应处理。
- CallerRunsPolicy:当任务被拒绝时,由调用线程(提交任务的线程)来执行该任务。这样可以降低新任务的提交速度,同时保证任务不会丢失,但可能会影响调用线程的性能。
- DiscardPolicy:直接丢弃被拒绝的任务,不做任何处理。适用于可以容忍部分任务丢失的场景,如一些日志记录任务。
- DiscardOldestPolicy:丢弃队列中最老的任务(即最先进入队列的任务),然后尝试提交新任务。适用于新任务比老任务更重要,且不希望任务队列无限增长的场景。