面试官一个线程池问题把我问懵逼了。 (中)

简介: 面试官一个线程池问题把我问懵逼了。 (中)

巧了嘛,这不是。顺序刚好是:

  • Thread[test-1-3,5,main]
  • Thread[test-1-2,5,main]
  • Thread[test-1-1,5,main]

消费者这边我们大概摸清楚了,接着去看看生产者。

  • java.util.concurrent.ThreadPoolExecutor#execute

image.png

线程池是在这里把任务放到队列里面去的。

而这个方法里面的源码是这样的:

image.png

其中signalNotEmpty() 最终会走到 doSignal 方法,而该方法里面会调用 transferForSignal 方法。

这个方法里面会调用 LockSupport.unpark(node.thred) 方法,唤醒线程:

image.png

而唤醒的顺序,就是等待队列里面的顺序:

image.png

所以,现在你知道当一个任务来了之后,这个任务该由线程池里面的哪个线程执行,这个不是随机的,也不是随便来的。

是讲究一个顺序的。

什么顺序呢?

Condition 里面的等待队列里面的顺序。

什么,你不太懂 Condition?

那还不赶紧去学?等着我给你讲呢?

本来我是想写一下的,后来发现《Java并发编程的艺术》一书中的 5.6.2 小节已经写的挺清楚了,图文并茂。这部分内容其实也是面试的时候的高频考点,所以自己去看看就好了。

image.png

先欠着,欠着

image.png


非核心线程怎么回收?


还是上面的例子,假设非核心线程就空闲了超过 30 秒,那么它是怎么被回收的呢?

这个也是一个比较热门的面试题。

这题没有什么高深的地方,答案就藏在源码的这个地方:

  • java.util.concurrent.ThreadPoolExecutor#getTask


image.png

当 timed 参数为 true 的时候,会执行 workQueue.poll(keepAliveTime,TimeUnit.NANOSECONDS) 方法。

而 timed 什么时候为 true 呢?

  • boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

allowCoreThreadTimeOut 默认为 false。

image.png

所以,就是看 wc > corePoolSize 条件,wc 是活跃线程数。此时活跃线程数为 3 ,大于核心线程数 2。

因此 timed 为 true。

也就是说,当前 workQueue 为空的时候,现在三个线程都阻塞 workQueue.poll 方法中。

而当指定时间后,workQueue 还是为空,则返回为 null。

于是在 1077 行把 timeOut 修改为 true。

进入一下次循环,返回 null。

最终会执行到这个方法:

  • java.util.concurrent.ThreadPoolExecutor#processWorkerExit


image.png

目录
相关文章
|
4月前
|
存储 安全 Java
【Java集合类面试二十五】、有哪些线程安全的List?
线程安全的List包括Vector、Collections.SynchronizedList和CopyOnWriteArrayList,其中CopyOnWriteArrayList通过复制底层数组实现写操作,提供了最优的线程安全性能。
|
15天前
|
存储 缓存 算法
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
本文介绍了多线程环境下的几个关键概念,包括时间片、超线程、上下文切换及其影响因素,以及线程调度的两种方式——抢占式调度和协同式调度。文章还讨论了减少上下文切换次数以提高多线程程序效率的方法,如无锁并发编程、使用CAS算法等,并提出了合理的线程数量配置策略,以平衡CPU利用率和线程切换开销。
面试官:单核 CPU 支持 Java 多线程吗?为什么?被问懵了!
|
3月前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
3月前
|
消息中间件 前端开发 NoSQL
面试官:线程池遇到未处理的异常会崩溃吗?
面试官:线程池遇到未处理的异常会崩溃吗?
78 3
面试官:线程池遇到未处理的异常会崩溃吗?
|
3月前
|
消息中间件 存储 前端开发
面试官:说说停止线程池的执行流程?
面试官:说说停止线程池的执行流程?
53 2
面试官:说说停止线程池的执行流程?
|
3月前
|
消息中间件 前端开发 NoSQL
面试官:如何实现线程池任务编排?
面试官:如何实现线程池任务编排?
36 1
面试官:如何实现线程池任务编排?
|
4月前
|
安全 Java
【Java集合类面试十三】、HashMap如何实现线程安全?
实现HashMap线程安全的方法包括使用Hashtable类、ConcurrentHashMap,或通过Collections工具类将HashMap包装成线程安全的Map。
【多线程面试题 一】、 创建线程有哪几种方式?
创建线程的三种方式包括继承Thread类、实现Runnable接口和实现Callable接口,其中Runnable和Callable接口方式更受推荐,因为它们允许多重继承并更好地体现面向对象思想。
|
4月前
|
Java 调度
【多线程面试题 五】、 介绍一下线程的生命周期
线程的生命周期包括新建、就绪、运行、阻塞和死亡状态,线程状态会根据线程的执行情况在这些状态之间转换。
【多线程面试题 五】、 介绍一下线程的生命周期
|
4月前
|
存储 安全 Java
【多线程面试题十七】、如果不使用synchronized和Lock,如何保证线程安全?
这篇文章探讨了在不使用`synchronized`和`Lock`的情况下保证线程安全的方法,包括使用`volatile`关键字、原子变量、线程本地存储(`ThreadLocal`)以及设计不可变对象。