简介
在Thread
类中有个有个内部接口UncaughtExceptionHandler
,这个接口定义了线程运行时遇到未被捕获的异常的规范,一般不设置这个处理器的时候,线程如果遇到未被捕获的异常则会终止。设置这个处理器之后可以用于统一处理线程抛出的异常。
在Thread中有2个方法可以设置未捕获的异常处理:
setDefaultUncaughtExceptionHandler()
这个方法是静态,用于设置一个默认的全局异常处理器。setUncaughtExceptionHandler()
这个方法是针对某个Thread对象的,可以用于对特定的线程进行未捕获的异常处理。
示例
线程由于异常终止的示例
下面展示一个由于异常未被捕获而导致线程终止的例子:
/**
* 线程由于异常未被捕获导致线程终止的例子
* @author RJH
* 2017年11月21日
*/
public class TerminatedByUncaughtExceptionDemo {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
private int i = 0;
@Override
public void run() {
while (true) {//死循环自增
++i;
if (i > 2) {//大于2则抛出异常
throw new RuntimeException("i is bigger than 2");
}
}
}
});
thread.start();
//线程如果依然存活,则死循环
while (thread.isAlive()) {
}
//此时线程已终止,状态为TERMINATED
System.out.println(thread.getState());
}
}
运行结果
Exception in thread "Thread-0" java.lang.RuntimeException: i is bigger than 2
at com.rjh.thread.TerminatedByUncaughtExceptionDemo$1.run(TerminatedByUncaughtExceptionDemo.java:14)
at java.lang.Thread.run(Thread.java:745)
TERMINATED
这里需要注意Thread和Runnable中只能抛出RuntimeException
,这是由于Runnable中的run()方法定义所导致的。
异常处理器示例
下面就用这个异常处理器实现一个模拟全局的日志记录的例子,这个例子的注释都比较齐全,大家只要看着注释基本就能明白了:
import java.lang.Thread.UncaughtExceptionHandler;
/**
* 线程异常处理器的例子
* @author RJH
* @date 2017年11月21日 下午9:32:13
*/
public class UncaughtExceptionHandlerDemo {
public static void main(String[] args) {
//设置一个全局的异常处理器
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
//用系统异常输出流输出类似日志的信息(其实就是模拟日志),格式是 时间戳 线程名称 异常名称 异常信息
//这里在实际开发的时候要记得把异常堆栈也打印出来,这样便于排查问题
System.err.println(String.format("%d %s %s",System.currentTimeMillis(),t.getName(),e.toString()));
}
});
//通过for循环启动多个线程
for(int i=0;i<5;i++){
Thread t=new ExceptionThread();
t.start();
}
}
/**
* 抛出异常的线程,一般情况下最好还是不要继承Thread,建议是实现Runnable接口
* @author RJH
* @date 2017年11月21日 下午9:36:46
*/
private static class ExceptionThread extends Thread{
private int i=10;
@Override
public void run(){
while(10/i>0){//i不断自减,最后会抛出一个ArithmeticException
--i;
}
}
}
}