type
status
date
slug
summary
tags
category
icon
password
example-row
example-row
当单线程的程序发生一个未捕获的异常时我们可以采用try....catch进行异常的捕获,但是在多线程环境中,线程抛出的异常是不能用try....catch捕获的,这样就有可能导致一些问题的出现,比如异常的时候无法回收一些系统资源,或者没有关闭当前的连接等等。

普通try....catch

运行结果:
可以看到在多线程中通过try....catch试图捕获线程的异常是不可取的。Threadrun方法是不抛出任何检查型异常的,但是它自身却可能因为一个异常而被中止,导致这个线程的终结。

主动处理多线程中未捕获异常

如果任务抛出了一个未检查异常,那么它将使线程终结,但会首先通知框架该现场已经终结。然后框架可能会用新的线程来代替这个工作线程,也可能不会,因为线程池正在关闭,或者当前已有足够多的线程能满足需要。当编写一个向线程池提交任务的工作者类线程类时,或者调用不可信的外部代码时(例如动态加载的插件),使用这些方法中的某一种可以避免某个编写得糟糕的任务或插件不会影响调用它的整个线程。
 
运行结果:

使用UncaughtExceptionHandle处理多线程中未捕获异常

Thread API中同样提供了UncaughtExceptionHandle,它能检测出某个由于未捕获的异常而终结的情况。这两种方法是互补的,通过将二者结合在一起,就能有效地防止线程泄露问题。

设置默认UncaughtExceptionHandler处理多线程中未捕获异常

可以为所有的Thread设置一个默认的UncaughtExceptionHandler,通过调用Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)方法,这是Thread的一个static方法。
运行结果:

线程池excuse方法中处理多线程中未捕获异常

如果换成线程池执行execute的方法发生异常
ExceptionHandler同上面例子,运行结果:
可以看到并未捕获到异常。可以通过将异常的捕获封装到Runnable或者Callable来处理多线程中未捕获异常:
运行结果:

线程池submit方法中处理多线程中未捕获异常

只有通过execute提交的任务,才能将它抛出的异常交给UncaughtExceptionHandler,而通过submit提交的任务,无论是抛出的未检测异常还是已检查异常,都将被认为是任务返回状态的一部分。如果一个由submit提交的任务由于抛出了异常而结束,那么这个异常将被Future.get封装在ExecutionException中重新抛出。
例子1:
例子2:
例子1和例子2运行结果都是:
submit方法下,捕获异常的处理方式如下:
运行结果:

参考

 
【java笔记009】线程池的使用【java web001】tomcat
  • Twikoo