最近项目里一个发送短消息的线程老是死掉,初步怀疑是由于网络原因。又不想弄个线程监视之类的,搜了一下 UncaughtExceptionHandler 刚好可以解决。
线程运行时抛出的运行时异常使用try catch 是无法捕捉到的,此时往往导致线程停止正常工作。
一、首先要写一个线程异常抛出后处理类,实现UncaughtExceptionHandler 接口,我的做法是发送一封系统内部邮件给管理员:
/**
* 线程执行错误后,发送一份内部邮件给管理员,要求线程在创建之后必须设置 setUncaughtExceptionHandler
* @author HAIQING
*
*/
public class SmsSendExceptionHandler implements UncaughtExceptionHandler {
private static final Logger log = Logger.getLogger(SmsSendExceptionHandler.class);
public void uncaughtException(Thread t, Throwable e) {
String threadname=t.getClass().getName();//获得线程名
String subject="线程:"+t.getName()+"抛出异常,请检查";
StringWriter sw=new StringWriter();
PrintWriter pw=new PrintWriter(sw);
e.printStackTrace(pw);
String msg=sw.toString();//拿到线程报错的详细信息
String body="线程状态:"+t.getState()+"。类路径:"+t.getClass().getName()+"。异常详细信息:"+sw.toString();
log.error(sw.toString());
//以下代码是使用 反射机制 重新创建线程
// try {
// Class tempclass=Class.forName(t.getClass().getName());
// t=(Thread)tempclass.newInstance();
// SmsSendExceptionHandler smsHandler=new SmsSendExceptionHandler();
// t.setUncaughtExceptionHandler(smsHandler);
// t.start();
// log.info(threadname+"。重新创建实例并执行!");
// } catch (ClassNotFoundException e1) {
// e1.printStackTrace();
// log.error("线程类路径:"+threadname+"未发现", e1);
// } catch (InstantiationException e1) {
// e1.printStackTrace();
// log.error("线程类:"+threadname+"创建失败", e1);
// } catch (IllegalAccessException e1) {
// e1.printStackTrace();
// log.error("线程类:"+threadname+"创建失败", e1);
// }
}
}
二、线程创建时,设置一下:
SmsSendExceptionHandler smsHandler=new SmsSendExceptionHandler();
SmsServiceThread smsSendThread = new SmsServiceThread();
smsSendThread.setUncaughtExceptionHandler(smsHandler);
smsSendThread.start();
原线程不需更改,这样当线程执行中,抛出运行时异常后便可以到 SmsSendExceptionHandler 中 执行 uncaughtException 方法。此时可得到 该线程信息和异常信息(Thread t, Throwable e);