写此文档目的主要是我在开发程序过程中设置了未捕获异常处理器,用ExecutorService接口的submit方法提交子线程任务,而子线程运行发生异常,但是并未回调异常处理器,就出现了子线程未运行成功也没有任何Log的”诡异“现象。
在Java层,我们创建子线程的常用方式有:
1.继承Thread,重写run();
2.实现Runnable接口,重写run();
3.使用线程池ExecutorService接口或ThreadPoolExecutor提交子任务。
ThreadPoolExecutor就是ExecutorService接口的实现子类。我们拿这两个类进行说明,它们的submit方法都是AbstractExecutorService类实现的。
如何捕获或处理子线程异常?这时你可能会说,我们直接在子线程启动的语句使用try…catch包裹不就行了吗?这是不可行的,捕获不到异常,为什么?(此问题标记为 问题1)
仔细查看Thread类,发现它提供了一个设置未捕获异常处理器的方法:
就是为整个应用程序设置未捕获异常的处理器,当程序发生未捕获异常时(包含子线程未捕获异常),JVM直接移交我们的异常处理器处理。
这种方法只适用于主线程、上述线程创建方式的1、2以及通过ExecutorService接口类、ThreadPoolExecutor类的execute方法提交任务的方式。也就是通过ExecutorService接口类、ThreadPoolExecutorr类的submit方法提交的线程任务如果发生了运行时异常也不会回调我们的异常处理器。为什么?(此问题标记为 问题2)
通过ExecutorService接口或ThreadPoolExecutor类都具有execute、submit两种方式提交子任务:
ExecutorService接口或ThreadPoolExecutor类的execute方法只能接受Runnable类型的任务,但submit还可以接受Callable类型的任务。那么Runnable和Callable类型的任务有什么区别呢?