ThreadPoolExecutor 线程池异常消失之刨根问底 (2)

4.为了验证第三步的解释,我们在 Thread 类中 run 方法与 Worker 类中的 run 方法,分别打上断点,再运行。发现,确实和我们预想的一样,程序先进入了 Thread 类中run 方法,后调用了Worker类中的 run 方法,继而调用了Worker类中 runWorker 方法。

线程池

线程池

5.那么现在,我们再看一下runWorker干了什么事情?我们发现runWorker获取了Worker对象的Runnable task(也就是我们创建的任务),并且调用了我们任务的run 方法。

线程池

线程池

6.OK,我们现在只需要看一下,runWorker task.run()方法调用这里的异常处理,就明白了。我们发现,此处运行有异常捕获,try catch 了Throwable 异常,且向上抛出了,而我们的程序除数取到 0 的异常ArithmeticException,也包括在其中。

线程池

线程池

注释:看到这我们就明白了,前面的程序为什么execute方法会抛出异常了吧,行吧,都散了吧。什么,我才刚看爽,你就叫我走?还有submit呢,为啥不抛异常啊,什么情况还没说呢,别想溜。。。好吧,咱们继续看下 submit的底层实现。

submit实现

1.首先咱们来看一下submit方法的实现,发现程序会将我们提交的任务通过newTaskFor方法转换成FutureTask
2.任务转换成FutureTask后会调用与前面一样的execute 方法

线程池

线程池

3.看到这我们就知道了,也就是说后面还是重复着前面execute执行相同的逻辑,只不过参数变成了FutureTask,那么最后在runWorker方法里面 task.run() 那里,会走FutureTask类的 run 方法,去调用我们定义的任务。
4.所以我们去FutureTask类中,看一下 run方法的实现。我们发现run 方法中 try catch了异常,并且调用了setException 方法,但是在setException方法中,将异常赋给了outcome,未见其他处理。

线程池

5.最后我们看一下FutureTask整个类中outcome 出现的地方,发现在get 方法中通过调用 report 方法返回了 outcome。

线程池

6.所以我们在程序那里,通过get方法去接收,看一下出现什么结果?结果同execute方法一样出现了异常。

Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191) at com.tiny.juc.boot.pool.ExceptionMissMain.main(ExceptionMissMain.java:39)

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzxxww.html