Java线程池线程异常且异常处理器失效的“诡异”现象

本文探讨了Java线程池中通过submit方法提交任务时,子线程异常未回调异常处理器的现象。分析了线程池的工作原理,解释了由于FutureTask的try...catch结构,异常被内部捕获,导致无法通过未捕获异常处理器捕获。同时,介绍了通过execute方法提交的任务在发生异常时,JVM会回调异常处理器。
摘要由CSDN通过智能技术生成

  写此文档目的主要是我在开发程序过程中设置了未捕获异常处理器,用ExecutorService接口的submit方法提交子线程任务,而子线程运行发生异常,但是并未回调异常处理器,就出现了子线程未运行成功也没有任何Log的”诡异“现象。

  在Java层,我们创建子线程的常用方式有:
  1.继承Thread,重写run();
  2.实现Runnable接口,重写run();
  3.使用线程池ExecutorService接口或ThreadPoolExecutor提交子任务。

  ThreadPoolExecutor就是ExecutorService接口的实现子类。我们拿这两个类进行说明,它们的submit方法都是AbstractExecutorService类实现的。
  如何捕获或处理子线程异常?这时你可能会说,我们直接在子线程启动的语句使用try…catch包裹不就行了吗?这是不可行的,捕获不到异常,为什么?(此问题标记为 问题1)

  仔细查看Thread类,发现它提供了一个设置未捕获异常处理器的方法:
图1.1 Thread类的设置异常处理器方法
  就是为整个应用程序设置未捕获异常的处理器,当程序发生未捕获异常时(包含子线程未捕获异常),JVM直接移交我们的异常处理器处理。
这种方法只适用于主线程、上述线程创建方式的1、2以及通过ExecutorService接口类、ThreadPoolExecutor类的execute方法提交任务的方式。也就是通过ExecutorService接口类、ThreadPoolExecutorr类的submit方法提交的线程任务如果发生了运行时异常也不会回调我们的异常处理器。为什么?(此问题标记为 问题2)
  通过ExecutorService接口或ThreadPoolExecutor类都具有execute、submit两种方式提交子任务:
图1.2 线程池提交任务的execute方法
图1.3 线程池提交任务的submit方法
  ExecutorService接口或ThreadPoolExecutor类的execute方法只能接受Runnable类型的任务,但submit还可以接受Callable类型的任务。那么Runnable和Callable类型的任务有什么区别呢?
图1.4 Runnable接口与Callable接口

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值