也许ThreadGroup提供的有用的功能之一就是uncaughtException方法了。Java提供了强大的异常处理机制,有些异常可以通过try/catch捕获或者re-throw,这些都是checked exception,比如IOException和ClassNotFoundException,还有一些是不必要捕获处理的,如NumberFormatException.
在Java多线程中提供了一个层次化的机制帮助我们有效的处理uncaught exception. 当一个线程抛出异常时,JVM首先会调用thread里面指定的uncaught exception handler处理异常,如果在thread级没有设置handler,JVM会到当前线程所在的组的exception handler处理异常,如果线程组没有定义uncaughtException方法,JVM会继续寻找上一级的exception handler处理。如果一个handler都没有找到,这默认打出错误栈并推出程序。
让们看一个具体的例子:
import java.lang.Thread.UncaughtExceptionHandler; public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.printf("Uncaught exception raised and captured in thread %s : \n", t.getName()); } } import java.lang.Thread.UncaughtExceptionHandler; public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler { @Override public void uncaughtException(Thread t, Throwable e) { System.out.printf("Uncaught exception raised and captured in thread %s : \n", t.getName()); } } public class MyThreadGroupWithExceptionHandler extends ThreadGroup { public MyThreadGroupWithExceptionHandler(String name) { super(name); } @Override public void uncaughtException(Thread t, Throwable e) { System.out.printf("Uncaught exception caught in thread group's uncaughtException %s.\n",this.getName()); interrupt(); } } public class TestUncaughtException { public static void main(String[] args){ MyTask task1 = new MyTask(); Thread t1 = new Thread(task1,"UncaughtException Task"); t1.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler()); t1.start(); MyThreadGroupWithExceptionHandler group1 = new MyThreadGroupWithExceptionHandler("mythread"); MyTask task2 = new MyTask(); Thread t2 = new Thread(group1, task2,"Task with group exception handler"); t2.start(); ThreadGroup group2 = new ThreadGroup("mythread"); MyTask task3 = new MyTask(); Thread.setDefaultUncaughtExceptionHandler(new MyDefaultExceptionHandler()); Thread t3 = new Thread(group2, task3, "Task with exception caught by Thread.default"); t3.start(); } }
输出可见异常分别在Thread实例,ThreadGroup,Thread级别被捕获。