答完这道线程池场景题,面试官让我回家等通知

本文探讨了一道面试题,涉及线程池在处理任务时的机制。当有100个任务进入一个核心线程数为10,最大线程数为20,任务队列为100的线程池时,答案可能因线程池类型而异。正常情况下,会先启动10个核心线程,剩余任务进入队列。但在EagerThreadPoolExecutor中,会立即启动20个线程,剩余任务进入队列。理解线程池的工作原理对于避免面试陷阱至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

一道面试题开始~~面试官:"假设我们有一个线程池,核心线程数为10,最大线程数也为20,任务队列为100。现在来了100个任务,线程池里现在有几个线程运行?"粉丝豪:"应该是10吧。"面试官:"你确定?"粉丝豪:"确定啊,就是10…"于是乎,粉丝豪就回去等通知了~

此题的陷阱,大家如果看出来了,本文就不用看了!其实这道题正确的答案是"不一定!"因为并没指明是哪一种线程池机制,带着我们的疑问继续往下看!

ps:不要纠结这题是不是咬文嚼字,现在人多如米,题目就是这样坑~

正文

先进队列,到最大值,再起线程

这种情况是大家最容易想到的情况,因为JDK中的线程池,也就是ThreadPoolExecutor就是这种机制的!

OK,我们先来看一下ThreadPoolExecutor的execute方法,如下图所示


看到三个红框了吧(其实源码里有解释),对应的三步分别是

  • (1)判断当前活跃线程数是否小于corePoolSize,如果小于,则调用addWorker创建线程执行任务
  • (2)如果不小于corePoolSize,则将任务添加到workQueue队列
  • (3)如果放入workQueue失败,则创建线程执行任务,如果这时
<think>嗯,用户让我介绍一下线程池的高频面试。我需要先整理线程池相关的核心知识点,然后确定哪些是面试中经常被问到的。首先,线程池的基本概念是必须的,比如为什么使用线程池,它的优点是什么。然后,线程池的参数,比如核心线程数最大线程数、队列这些,肯定是重点。接着,线程池的工作流程,任务提交后的处理流程,这也是常见的问。 还有线程池的拒绝策略,不同的策略有哪些,应用场景是什么。可能还需要提到常见的线程池类型,比如FixedThreadPool、CachedThreadPool等,以及它们的区别和潜在问,比如为什么推荐自定义线程池而不是用Executors创建的。另外,线程池的生命周期状态,比如RUNNING、SHUTDOWN等,以及如何关闭线程池的方法,shutdown和shutdownNow的区别。 线程池的参数如何设置,尤其是核心线程数最大线程数的确定,可能涉及CPU密集型、IO密集型的任务类型。还有动态调整线程池参数的可能性,比如在运行中修改核心线程数。另外,线程池的监控,比如如何获取线程池的运行状态,任务成数等指标。 还有可能问到线程池中线程复用的原理,即如何通过Worker类不断地从队列中获取任务执行。或者线程池中的异常处理机制,如何处理未捕获的异常。可能还有实际应用中的问,比如在Spring中如何使用线程池,如何配置等。 需要确保覆盖这些点,并且结构清晰,分点回。可能还要举一些例子,比如线程池处理任务的流程示意图,或者拒绝策略的具体实现类。同时要注意避免错误,比如线程池的工作队列类型,不同的队列对线程池行为的影响,比如有界队列和无界队列的区别。 另外,要提醒用户注意线程池可能引发的内存溢出问,比如使用无界队列导致任务堆积。还有线程池的线程工厂,如何自定义线程名称等。可能还有线程池的预热,比如预先启动核心线程。还有线程池的钩子方法,比如beforeExecute和afterExecute的使用。 总结下来,高频面试大概包括以下几个方面: 1. 线程池的作用和优点 2. 线程池核心参数及其作用 3. 线程池的工作流程 4. 拒绝策略的种类和应用 5. 常见的线程池类型及其问 6. 如何合理配置线程池参数 7. 线程池的生命周期和关闭方式 8. 线程池的底层实现原理 9. 异常处理机制 10. 动态调整参数和监控 需要将这些内容组织成结构化的回,分点说明,每个点给出简明扼要的解释,确保用户容易理解,同时覆盖常见的面试考点。</think>### 线程池高频面试解析 #### 1. 线程池的作用与优点 - **作用**:管理多个线程的生命周期,复用线程资源,避免频繁创建/销毁线程的开销。 - **优点**: - **资源复用**:减少线程创建/销毁的性能损耗。 - **控制并发**:通过参数限制线程数量,防止资源耗尽。 - **任务管理**:使用队列缓冲任务,支持异步执行。 --- #### 2. 线程池核心参数 线程池通过 `ThreadPoolExecutor` 的构造函数配置,核心参数如下: $$ \text{ThreadPoolExecutor}(corePoolSize, maxPoolSize, keepAliveTime, timeUnit, workQueue, threadFactory, handler) $$ - **corePoolSize**:核心线程数(长期保留的线程)。 - **maxPoolSize**:最大线程数(临时线程数上限)。 - **keepAliveTime**:非核心线程空闲存活时间。 - **workQueue**:任务队列(如 `ArrayBlockingQueue`, `LinkedBlockingQueue`)。 - **handler**:拒绝策略(当队列满且线程数达上限时触发)。 --- #### 3. 线程池工作流程 1. 提交任务后,优先使用核心线程执行。 2. 核心线程全忙时,任务进入队列等待。 3. 队列满时,创建临时线程(不超过 `maxPoolSize`)。 4. 线程数达 `maxPoolSize` 且队列满时,触发拒绝策略。 --- #### 4. 拒绝策略(RejectedExecutionHandler) - **AbortPolicy**(默认):直接抛出 `RejectedExecutionException`。 - **CallerRunsPolicy**:由提交任务的线程直接执行任务。 - **DiscardPolicy**:静默丢弃新任务。 - **DiscardOldestPolicy**:丢弃队列中最旧的任务,尝试重新提交。 --- #### 5. 常见线程池类型(Executors 创建) - **FixedThreadPool**:固定线程数,使用无界队列(可能导致OOM)。 - **CachedThreadPool**:线程数无上限,适合短时异步任务(可能创建过多线程)。 - **SingleThreadExecutor**:单线程执行(无界队列,任务顺序执行)。 - **ScheduledThreadPool**:支持定时/周期性任务。 **注意**:阿里开发规范建议手动创建 `ThreadPoolExecutor`,避免使用 `Executors`(隐含无界队列或线程数风险)。 --- #### 6. 参数配置原则 - **CPU 密集型**:核心线程数 ≈ CPU 核数(避免过多线程竞争)。 - **IO 密集型**:核心线程数可增大(如 `2 * CPU核数`),充分利用等待时间。 - **混合型任务**:拆分线程池或通过压测确定最优值。 --- #### 7. 线程池生命周期 - **RUNNING**:接受新任务,处理队列任务。 - **SHUTDOWN**:不再接受新任务,处理队列剩余任务。 - **STOP**:中断所有任务,不再处理队列。 - **TIDYING**:所有任务终止,线程数为0。 - **TERMINATED**:线程池彻底终止。 **关闭方法**: - `shutdown()`:平滑关闭(处理队列任务)。 - `shutdownNow()`:立即中断所有线程(返回未处理任务列表)。 --- #### 8. 底层实现原理 - **Worker 类**:封装线程和任务,通过 `runWorker()` 循环从队列获取任务。 - **任务执行**:核心线程通过 `while (task != null || (task = getTask()) != null)` 保持存活。 --- #### 9. 异常处理 - **try-catch**:在任务代码中捕获异常。 - **UncaughtExceptionHandler**:为线程设置全局异常处理器。 - **afterExecute()**:重写 `ThreadPoolExecutor` 的钩子方法捕获异常。 --- #### 10. 动态调整与监控 - **动态参数**:JDK 允许运行时修改 `corePoolSize` 和 `maxPoolSize`。 - **监控指标**: - `getCompletedTaskCount()`:已成任务数。 - `getActiveCount()`:活动线程数。 - `getQueue().size()`:队列中待处理任务数。 --- ### 高频问示例 1. 线程池参数如何设置?为什么不能直接用 `Executors` 创建? 2. 任务提交后,线程池的处理流程是什么? 3. 拒绝策略有哪些?线上突发流量如何选择策略? 4. `shutdown()` 和 `shutdownNow()` 的区别? 5. 如何排查线程池导致的内存溢出? 通过掌握以上知识点,可覆盖90%的线程池面试
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值