关于多线程中抛异常的这个面试题我再说最后一次! (2)

简介: 关于多线程中抛异常的这个面试题我再说最后一次! (2)

两种情况都和 future.get 方法有关,那我们就从这个方法的源码入手。


这个 Future 是一个接口:


image.png


而这个接口有非常多的实现类。我们找哪个实现类呢?


就是下面这个实现类:


java.util.concurrent.FutureTask


至于是怎么找到它的,你慢慢往后看就知道了。


先看看 FutureTask 的 get 方法:


image.png


get 方法的逻辑很简单,首先判断当前状态是否已完成,如果不是,则进入等待,如果是,则进入 report 方法。


一进 get 方法,我们就看到了 state 这个东西,这是 FutureTask 里面一个非常重要的东西:


image.png


所以,一目了然,一个任务的终态有四种:NORMAL、EXCEPTIONAL、CANCELLED、INTERRUPTED。


而我们主要关心 NORMAL、EXCEPTIONAL。


所以再回头看看 get 方法:


image.png


如果当前状态是小于 COMPLEING 的。


也就是当前状态只能是 NEW 或者 COMPLEING,总之就是任务还没有完成。所以进入 awaitDone 方法。这个方法不是本文关心的地方,接着往下看。


程序能往下走,说明当前的状态肯定是下面圈起来的状态中的某一个:


image.png


这个方法是干啥的?


注解说的很清楚了:对于已经完成了的 task,返回其结果或者抛出异常。


这里面的逻辑就很简单了,把 outcome 变量赋值给 x 。


然后判断当前状态,如果是 NORMAL,即 2,说明正常完成,直接返回 x。


如果是大于等于 CANCELLED,即大于等于 4 ,即这几种状态,就抛出 CancellationException。


剩下的情况就抛出 ExecutionException。


image.png


而这个“剩下的情况”是什么情况?


不就只剩下一个 EXCEPTIONAL 的情况了。


所以,经过前面的描述,我们可以总结一下。


当 FutureTask 的 status 为 NORMAL 时正常返回结果,当 status 为 EXCEPTIONAL 时抛出异常。


而当终态为 NORMAL 或者 EXCEPTIONAL 时,按照注释描述,状态的流程只能是这样的:


image.png



那么到底是不是这样的呢?


这就需要我们去线程池里面验证一下了。


寻找答案-线程池


先回答上一节的一个问题:我怎么知道是看 Future 这个接口的 FutureTask 这个实现类的:


image.png


image.png


可以看到,FutureTask 的构造方法里面默认了状态为 NEW。


然后直接在 runWorker 方法的 task.run 方法处打上断点:


image.png


这个 task 是一个 FutureTask,所以 run 方法其实是 FutureTask 的 run 方法。


跟着断点进去之后,就是 FutureTask 的 run 方法:


image.png


答案都藏在这个方法里面。


java.util.concurrent.FutureTask#run


标号为 ① 的地方是执行我们的任务,call 的就是示例代码里面的 sayHi 方法。


如果 sayHi 方法没有捕获运行时异常,则会在标号为 ② 的这个 catch 里面被捕获。然后执行标号为 ② 的这个代码。


如果 sayHi 方法捕获了运行时异常,则会进入标号为 ③ 的这个逻辑里面。


我们分别看一下标号为 ② 和 ③ 的逻辑:


image.png


目录
相关文章
|
29天前
|
Java 数据库连接 调度
面试题:用过线程池吗?如何自定义线程池?线程池的参数?
字节跳动面试题:用过线程池吗?如何自定义线程池?线程池的参数?
28 0
|
9天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
14天前
|
Java 调度
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
40 1
|
21天前
|
调度 Python
Python多线程、多进程与协程面试题解析
【4月更文挑战第14天】Python并发编程涉及多线程、多进程和协程。面试中,对这些概念的理解和应用是评估候选人的重要标准。本文介绍了它们的基础知识、常见问题和应对策略。多线程在同一进程中并发执行,多进程通过进程间通信实现并发,协程则使用`asyncio`进行轻量级线程控制。面试常遇到的问题包括并发并行混淆、GIL影响多线程性能、进程间通信不当和协程异步IO理解不清。要掌握并发模型,需明确其适用场景,理解GIL、进程间通信和协程调度机制。
31 0
|
26天前
|
存储 安全 Java
多线程编程常见面试题讲解(锁策略,CAS策略,synchronized原理,JUC组件,集合类)(下)
多线程编程常见面试题讲解(锁策略,CAS策略,synchronized原理,JUC组件,集合类)(下)
44 0
|
26天前
|
存储 安全 Java
多线程编程常见面试题讲解(锁策略,CAS策略,synchronized原理,JUC组件,集合类)(上)
多线程编程常见面试题讲解(锁策略,CAS策略,synchronized原理,JUC组件,集合类)
37 0
|
29天前
|
缓存 算法 安全
java多线程面试题
java多线程面试题
|
1天前
|
存储 安全 Java
【探索Linux】P.21(多线程 | 线程同步 | 条件变量 | 线程安全)
【探索Linux】P.21(多线程 | 线程同步 | 条件变量 | 线程安全)
5 0
|
1天前
|
算法 安全 Linux
【探索Linux】P.20(多线程 | 线程互斥 | 互斥锁 | 死锁 | 资源饥饿)
【探索Linux】P.20(多线程 | 线程互斥 | 互斥锁 | 死锁 | 资源饥饿)
4 0
|
1天前
|
存储 安全 Linux
【探索Linux】P.19(多线程 | 线程的概念 | 线程控制 | 分离线程)
【探索Linux】P.19(多线程 | 线程的概念 | 线程控制 | 分离线程)
4 0