大厂面试真题-简单说说线程池接到新任务之后的操作流程
线程池在接到新任务后的操作流程通常遵循以下步骤,这些步骤确保了任务的高效管理和执行。
一、判断当前线程状态
线程池首先会判断当前是否存在空闲线程,即没有正在执行任务且未被标记为死亡的线程。
- 有空闲线程:如果存在空闲线程,线程池会直接将新任务分配给该空闲线程执行。
- 无空闲线程:如果没有空闲线程,线程池则进入下一步的判断流程。
二、判断核心线程数
接下来,线程池会判断当前运行中的线程数是否小于核心线程数(corePoolSize)。
- 小于核心线程数:如果当前线程数小于核心线程数,线程池会创建一个新的核心线程,并将新任务分配给该线程执行。
- 大于等于核心线程数:如果当前线程数已达到或超过核心线程数,线程池则不会继续创建核心线程,而是进入下一步的判断流程。
三、判断阻塞队列
当核心线程数已满时,线程池会检查阻塞队列(workQueue)的状态。
- 队列未满:如果阻塞队列未满,线程池会将新任务添加到阻塞队列中等待执行。一旦有空闲线程出现,线程池会按照先进先出(FIFO)的规则从队列中取出任务并执行。
- 队列已满:如果阻塞队列已满,线程池则进入下一步的判断流程。
四、判断最大线程数
在阻塞队列已满的情况下,线程池会判断当前线程数是否已达到最大线程数(maximumPoolSize)。
-
未达到最大线程数:如果当前线程数未达到最大线程数,线程池会创建一个新的非核心线程(也称为临时线程或辅助线程),并将新任务分配给该线程执行。
-
达到最大线程数:如果当前线程数已达到最大线程数,线程池则无法再创建新的线程来执行任务。此时,线程池会采用拒绝策略(RejectedExecutionHandler)来处理新任务。常见的拒绝策略包括:
- AbortPolicy:直接抛出异常,这是默认策略。
- CallerRunsPolicy:由提交任务的线程(即调用者线程)来执行任务。
- DiscardOldestPolicy:丢弃阻塞队列中最靠前的任务(即最早进入队列但尚未执行的任务),然后执行当前任务。
- DiscardPolicy:直接丢弃任务,不做任何处理。
五、执行流程总结
综上所述,线程池接到新任务后的操作流程可以总结为以下步骤:
- 判断是否存在空闲线程,若存在则分配任务。
- 若无空闲线程,则判断当前线程数是否小于核心线程数,若小于则创建核心线程执行任务。
- 若核心线程数已满,则检查阻塞队列是否未满,若未满则将任务添加到队列中等待执行。
- 若阻塞队列已满,则判断当前线程数是否未达到最大线程数,若未达到则创建非核心线程执行任务。
- 若已达到最大线程数,则采用拒绝策略处理新任务。
这个流程确保了线程池能够高效地管理和执行任务,同时避免了资源的过度使用和浪费。