ToB企服应用市场:ToB评测及商务社交产业平台

标题: 付出宝面试太太太刁钻了!!如果把线程池 corePoolSize 设置为 0,会出现什 [打印本页]

作者: 熊熊出没    时间: 2024-5-15 20:22
标题: 付出宝面试太太太刁钻了!!如果把线程池 corePoolSize 设置为 0,会出现什
大家好,我是R哥。
最近做 Java 面试辅导,有个学员面试付出宝,遇到一个特殊故意思的问题:
如果把线程池 corePoolSize 设置为 0,会出现什么情况?


这个问题一说出来,我都感觉有点***钻。。
这几年我创作小程序:Java面试库,积累了 2700+ 的 Java 面试题,什么***钻的面试题没见过?
像这样的***钻面试题确实少见,阿里面试官是真的卷啊。。
大厂学员都觉得会抛异常,事实上真是这样吗?
我们来从源码来分析下,看看究竟!
先往返顾下线程池的工作流程:

1)如果线程池中的线程小于核心线程数 corePoolSize 时,则创建新线程直接执利用命。
2)如果线程池中的线程大于核心线程数 corePoolSize 时,则暂时把使命存储到工作队列 workQueue 中等待执行。
3)如果工作队列 workQueue 也满时:
更多参考我的更多 Java 多线程系列文章:https://www.javastack.cn/java/thread/
以下是 JDK 21 线程池类 ThreadPoolExecutor#execute 方法源码:
  1. public void execute(Runnable command) {
  2.     // 检查传入的任务是否为空,如果为空则抛出 NullPointerException
  3.     if (command == null)
  4.         throw new NullPointerException();
  5.     // 获取当前线程池的控制状态
  6.     int c = ctl.get();
  7.     // 步骤 1: 如果当前运行的线程数少于核心线程数
  8.     if (workerCountOf(c) < corePoolSize) {
  9.         // 尝试添加一个新的工作线程来执行提交的任务
  10.         // 如果添加成功,则直接返回
  11.         if (addWorker(command, true))
  12.             return;
  13.         
  14.         // 再次获取线程池的控制状态,以应对并发变化
  15.         c = ctl.get();
  16.     }
  17.     // 步骤 2
  18.     // 步骤 2.1: 如果线程池处于运行状态并且任务能够成功加入队列
  19.     if (isRunning(c) && workQueue.offer(command)) {
  20.         // 再次检查线程池的状态,确认线程池仍然处于运行状态
  21.         int recheck = ctl.get();
  22.         
  23.         // 2.2 如果线程池不再运行,并且任务能够从队列中移除,则拒绝任务
  24.         if (!isRunning(recheck) && remove(command))
  25.             reject(command);
  26.         
  27.         // 2.3 如果当前线程池没有运行的线程
  28.         else if (workerCountOf(recheck) == 0)
  29.             // 尝试添加一个新的非核心工作线程(false 表示非核心线程)
  30.             addWorker(null, false);
  31.     }
  32.     // 步骤 3
  33.     else {
  34.         // 3.1 尝试添加一个新的非核心工作线程来执行任务
  35.         if (!addWorker(command, false))
  36.             // 3.2 如果添加失败,说明线程池已关闭或达到饱和状态,因此拒绝任务
  37.             reject(command);
  38.     }
  39. }
复制代码
我检查了 JDK 8 和 JDK 17 两个主版本源码,这块的处理逻辑也是一样的。
从源码可以看到,如果往线程池提交使命的时间,当 corePoolSize = 0 时,代码正常情况下会执行到步骤2。
以下三步是关键步骤:
步骤 2.1:
此时,如果线程池处于运行状态,并且使命能够成功参加队列,分析线程池不为空,线程正常执利用命。
步骤 2.3:
此时,如果当火线程池没有运行的线程,则尝试添加一个新的非核心工作线程,即使命会先辈入队列列队再由线程获取使命执行。
步骤 3.1:
此时,分析队列满了无法参加使命,尝试添加一个新的非核心工作线程来执利用命,如果添加失败,分析线程池已关闭或达到饱和状态,因此拒绝使命。
扩展知识点:
这个逻辑在 JDK 6 之前略有不同,在 JDK 6 之前,当 corePoolSize = 0 的时间,先将这个使命放到壅闭队列中,只有等队列满了才创建线程来执行,而 JDK 6+ 是直接创建一个非核心线程,再放在队列中来执行,很显示,JDK 6 这个优化动作减小了内存溢出的可能性。
光说 JDK 6 和 JDK 8 这两个版本,对线程池的重构就很大,如今主流的版本都是 JDK 8+,这个相识一下就好。
这道题可以说是八股文之王了,我工作这么多年,面试过这么多人,也没有见过这道题。
对于阿里这样的大厂,可能会遇到奇奇怪怪的问题,不会很正常,说说本身的想法,大概不会太减分。但如果你恰悦目到了我的公众号,又学会了这道题,那下次有面试官问起,那就是加分题了,面试官也会对你眼前一亮。
像这样的面试八股文,我的小程序「Java面试库」还有许多,比如:
共 2700+,都是平时我面试别人,大概学员面试复盘积累下来的真题,不要在网上找七零八落的面试题了,浪费时间还轻易被误导。
最后,保举一波我的「面试辅导训练营」,有在看时机的,离职的、迷茫的,都可以参加我们的「面试辅导训练营」,大厂导师 1 v 1 辅导,帮你全面提拔面试综合实力,少走许多弯路,最大化提拔职场收益。
版权声明: 本文系公众号 "Java技术栈" 原创,转载、引用本文内容请注明出处,抄袭、洗稿一律投诉侵权,后果自负,并保留追究其法律责任的权利。
更多文章保举:
1.Spring Boot 3.x 教程,太全了!
2.2,000+ 道 Java面试题及答案整理(2024最新版)
3.免费获取 IDEA 激活码的 7 种方式(2024最新版)
觉得不错,别忘了随手点赞+转发哦!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4