多线程内抛出的异常,是不能正常通过try-catch来捕获并处理的,需要通过UncaughtExceptionHandler接口,它可以在每个Thread对象上附上异常处理器,并在线程抛出异常时被调用,我们只需通过ThreadFactory在每个新建的Thread对象上附上UncaughtExceptionHandler即可。
正常的异常处理机制无法捕获异常:
public class ExceptionThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
throw new RuntimeException();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
ExecutorService exec=Executors.newCachedThreadPool();
exec.execute(new ExceptionThread());
exec.shutdown();
}catch(RuntimeException e) {
System.out.println(e.getMessage());
}
}
}
输出:
Exception in thread "pool-1-thread-1" java.lang.RuntimeException
at cn.itcast.Thread.ExceptionThread.run(ExceptionThread.java:8)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
通过实现UncaughtExceptionHandler接口来捕获异常:
public class ExceptionThread implements Runnable {
@Override
public void run() {
// TODO Auto-generated method stub
throw new RuntimeException();
}
}
public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
//把获取异常的工作交由此处理器处理
@Override
public void uncaughtException(Thread t, Throwable e) {
// TODO Auto-generated method stub
System.out.println("caught:"+e);
}
}
public class HandlerThreadFactory implements ThreadFactory {
//设置需要捕获异常的线程
@Override
public Thread newThread(Runnable r) {
// TODO Auto-generated method stub
Thread t=new Thread(r);
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
return t;
}
}
public class ThreadExceptionTest {
public static void main(String[] args) {
// 将线程工厂传入线程池,则线程池启动的线程抛出的异常都将被MyUncaughtExceptionHandler捕获
ExecutorService exec=Executors.newCachedThreadPool(new HandlerThreadFactory());
exec.execute(new ExceptionThread());
exec.shutdown();
}
}
输出:caught:java.lang.RuntimeException
如果需要给创建的所有线程都设置这样的异常处理器,只需调用Thread的静态方法设置其为默认处理器:
public class ThreadExceptionTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
ExecutorService exec=Executors.newCachedThreadPool();
exec.execute(new ExceptionThread());
exec.shutdown();
}
}