美团面试官:核心线程数为0时,线程池如何执行?

开发 前端
当核心线程数为 0 时,当来了一个任务之后,会先将任务添加到任务队列,同时也会判断当前工作的线程数是否为 0,如果为 0,则会创建线程来执行线程池的任务,这就是正确的线程池执行流程,同时也是面试官想要的答案。

线程池是 Java 中用于提升程序执行效率的主要手段,也是并发编程中的核心实现技术,并且它也被广泛的应用在日常项目的开发之中。那问题来了,如果把线程池中的核心线程数设置为 0 时,线程池是如何执行的?

要回答这个问题,我们首先要了解在正常情况下,线程池的执行流程,也就是说当有一个任务来了之后,线程池是如何运行的?

1.线程池的执行流程

正常情况下(核心线程数不为 0 的情况下)线程池的执行流程如下:

  1. 判断核心线程数:先判断当前工作线程数是否大于核心线程数,如果结果为 false,则新建线程并执行任务。
  2. 判断任务队列:如果大于核心线程数,则判断任务队列是否已满?如果结果为 false,则把任务添加到任务队列中等待线程执行。
  3. 判断最大线程数:如果任务队列已满,则判断当前线程数量是否超过最大线程数?如果结果为 false,则新建线程执行此任务。
  4. 判断是否要执行拒绝策略:如果超过最大线程数,则将执行线程池的拒绝策略。

如下图所示:

图片图片

核心线程数 VS 最大线程数

核心线程数(corePoolSize)和最大线程数(maximumPoolSize)都是线程池中的两个重要参数,其中:

  1. 核心线程数定义了线程池中最小线程数量,即使这些线程处于空闲状态,也不会被销毁。
  2. 最大线程数定义了线程池中允许的最大线程数量,最大线程数等于核心线程数 + 临时线程数,最大线程数主要是提供了一种机制来应对突发的高并发请求,当有大量任务的时候,可以创建线程数量的上线。

PS:在线程池的使用过程中,最大线程数必须大于等于核心线程数,否则程序执行会报错。

2.核心线程为0的执行流程

那么问题来了,按照线程池的正常执行流程来看,如果核心线程数为 0 的话,那么当任务来了之后会判断当前工作的线程数不大于核心线程数,那也就不会创建线程执行任务了,会将任务放到队列。

但这个结果又很滑稽,有任务来了线程池竟然不执行,而是先放到任务队列中,这好像有比较奇怪,这就好比你开了一个快递店,当有快递来了之后,你想的不是如何派送,而是直接把它丢到仓库一样滑稽,这会让等快递的人很着急,所以,我们需要验证一下线程池的执行是否如我们猜想的那般,验证代码如下:

// 线程池核心线程数设置为 0
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                0, 10, 1, TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(10));
// 给线程池添加任务
threadPoolExecutor.execute(() -> {
    System.out.println("www.javacn.site");
});

最终程序的执行结果如下:

图片图片

咦,结果怎么不符合我们的预期呢?为什么任务来了之后,没有将任务放到任务队列而是直接执行了呢?

虽然程序执行结果符合正常逻辑,但又和我们了解的线程池执行理论相违背,这是什么原因呢?

查看线程池的执行源码

带着这个疑问,我们查看了线程池的执行源码发现,线程池的执行过程远比我们想想的复杂,线程池核心源码如下:

图片图片

从上面源码可以看出,当我们将任务添加到队列的时候,线程池会判断工作的线程数是否为 0,也就是上面圈出来的那行代码,如果当前工作线程为 0 的话,会创建线程执行任务。哦,原来如此,这样,就能将理论和实践对应上了。

也就是说,当核心线程数为 0 时,当来了一个任务之后,会先将任务添加到任务队列,同时也会判断当前工作的线程数是否为 0,如果为 0,则会创建线程来执行线程池的任务,这就是正确的线程池执行流程,同时也是面试官想要的答案。

责任编辑:武晓燕 来源: Java中文社群
相关推荐

2024-06-20 13:59:26

2024-09-12 08:35:06

2024-09-09 15:09:30

2024-04-02 09:45:27

线程池Executors开发

2023-05-22 08:17:04

2024-03-11 18:18:58

项目Spring线程池

2024-05-16 17:58:30

线程任务线程通讯线程池

2024-09-11 22:51:19

线程通讯Object

2021-11-29 10:55:11

线程池Java面试

2022-06-24 06:43:57

线程池线程复用

2024-10-31 09:30:05

线程池工具Java

2020-05-22 08:11:48

线程池JVM面试

2022-02-14 16:08:15

开源项目线程池动态可监控

2021-05-08 07:53:33

面试线程池系统

2021-03-29 08:47:24

线程面试官线程池

2023-12-20 14:35:37

Java虚拟线程

2021-04-08 10:51:10

主线程子线程Thread

2022-03-28 08:31:29

线程池定时任务

2010-08-27 10:53:14

面试

2023-11-29 16:38:12

线程池阻塞队列开发
点赞
收藏

51CTO技术栈公众号