线程的捕获异常
由于线程的特性使得不能捕获从现场逃逸的异常,一旦异常逃出run方法,他会向外传播到控制台,除非采取特别的方法来捕获这些异常。
public class ExceptionThread implements Runnable {
@Override
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) {
Executors.newCachedThreadPool().execute(new ExceptionThread());
}
}
异常传播到控制台:
使用try-catch 来捕获异常:
public class ExceptionThread implements Runnable {
@Override
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) {
try{
Executors.newCachedThreadPool().execute(new ExceptionThread());
}catch (Exception e) {
// TODO: handle exception
System.out.println("catch the exception:"+e);
}
}
}
控制台输出:
证明确实没有捕获到异常 异常传播到控制台了
为了解决这个问题,要修改线程产生的方式。Thread.UncatchExceptionHandler 是java SE5的新的接口,它允许在每个Thread上附着一个异常处理器。现在我们要定制一个ThreadFactory来定制ExecutorService来定制产生的线程的属性(这句话好拗口)
定制的ThreadFactory
public class HandlerThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
// TODO Auto-generated method stub
Thread t=new Thread(r);
t.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
// TODO Auto-generated method stub
System.out.println("catch the exception:"+e);
}
});
return t;
}
}
修改ExceptionThread
public class ExceptionThread implements Runnable {
@Override
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) {
Executors.newCachedThreadPool(new HandlerThreadFactory()).execute(new ExceptionThread());
}
}
输出:
通过输出可以看到,异常已经被捕获了。
从上面的定制的ThreadFactory中我们是逐个线程设置异常处理器
如果要在线程中处处设置相同的处理器可以使用 设置默认线程异常处理器的方法:
public class ExceptionThread implements Runnable {
@Override
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) {
//设置线程的默认异常处理器
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
// TODO Auto-generated method stub
System.out.println("catch the exception:"+e);
}
});
Executors.newCachedThreadPool().execute(new ExceptionThread());
}
}