Java 线程(Runnable)的异常处理, 以下的阐述均基于Runnable的线程实现
首先,有个问题,如果Java子线程发生异常会怎么样?实际上会导致该线程直接终止。当年自己写了个线程模型大概是这样的:
|
|
当时我一只担心步骤2的线程T会因为什么而挂掉,然后大家没办法上传文件。而当时完全不知道UncaughtExceptionHandler的存在,多希望有一丁点指导啊。
那么如何处理可能出现的异常而不至于线程直接挂掉呢?
第一,把整个run中的异常在内部捕获掉
第二,直接在线程中setUncaughtExceptionHandler,将异常处理与run分开。
其实,有的同学可能疑惑,为什么不能直接把整个线程用try-catch包裹起来。因为这本来就没有什么用,譬如:
|
|
假设t是从线程x中 new
出来的,那么x称为t的父线程。而线程与线程间的运行本是异步的(当然如果不使用线程间通信机制的情况下),有可能x在t还没结束时先结束,这是有可能的,如果x不是主线程的话。 所以,try-catch在异步的线程中捕获是没有意义的。
正确的方法是:
或者使用UncaughtExceptionHandler 捕获线程运行体的运行时异常,使用也很简单:
在线程中使用:
如果没有捕获异常,不会输出0,而有了handler则不影响下面的执行,会正常输出了。
或者是:
正如上面所写,在java 8中还可以用lamda表达式简化语法,用匿名handler代替。不过使用a.setUEH(handler)
这种方式是策略模式的体现,更容易在需要的时候随时替换handler的实现,正如sort函数的Comparator参数一样。