关于多线程中抛异常的这个面试题我再说最后一次! (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


目录
相关文章
|
3天前
|
消息中间件 前端开发 Java
美团面试:如何实现线程任务编排?
线程任务编排指的是对多个线程任务按照一定的逻辑顺序或条件进行组织和安排,以实现协同工作、顺序执行或并行执行的一种机制。 ## 1.线程任务编排 VS 线程通讯 有同学可能会想:那线程的任务编排是不是问的就是线程间通讯啊? 线程间通讯我知道了,它的实现方式总共有以下几种方式: 1. Object 类下的 wait()、notify() 和 notifyAll() 方法; 2. Condition 类下的 await()、signal() 和 signalAll() 方法; 3. LockSupport 类下的 park() 和 unpark() 方法。 但是,**线程通讯和线程的任务编排是
|
3天前
|
缓存 安全 Java
7张图带你轻松理解Java 线程安全,java缓存机制面试
7张图带你轻松理解Java 线程安全,java缓存机制面试
|
1天前
|
Oracle Java 关系型数据库
一次惨痛的面试:“网易提前批,我被虚拟线程问倒了”
一次惨痛的面试:“网易提前批,我被虚拟线程问倒了”
19 4
|
3天前
|
机器学习/深度学习 PyTorch 算法框架/工具
神经网络基本概念以及Pytorch实现,多线程编程面试题
神经网络基本概念以及Pytorch实现,多线程编程面试题
|
3天前
|
Java
阅读《代码整洁之道》总结(1),java多线程面试
阅读《代码整洁之道》总结(1),java多线程面试
|
4天前
|
Java
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
【Java多线程】面试常考 —— JUC(java.util.concurrent) 的常见类
24 0
|
4天前
|
安全 Java 程序员
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
【Java多线程】面试常考——锁策略、synchronized的锁升级优化过程以及CAS(Compare and swap)
12 0
|
4天前
|
监控 安全 Java
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
【多线程学习】深入探究阻塞队列与生产者消费者模型和线程池常见面试题
|
4天前
|
存储 安全 Java
这些年背过的面试题——多线程篇
本文是技术人面试系列多线程篇,面试中关于多线程都需要了解哪些基础?一文带你详细了解,欢迎收藏!
|
4天前
|
Java 调度
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
Java面试必考题之线程的生命周期,结合源码,透彻讲解!
46 1