在Java中有两种异常:

非运行时异常(Checked Exception): 这种异常必须在方法声明的throws语句指定,或者在方法体内捕获。例如:IOException和ClassNotFoundException

运行时异常(Unchecked Exception):这种异常不必在方法声明中指定,也不需要在方法体中捕获。例如:NumberFormatException

因为run()方法不支持throws语句,所以当线程对象的run()方法抛出非运行异常时,我们必须捕获并且处理他们。当运行时异常从run()方法中抛出时,默认行为是在控制台输出堆栈记录并且退出程序。

幸运的是,Java提供给我们一种在线程对象里捕获和处理运行时异常的一种机制。

在本节中,我们将通过范例学习这种机制。

准备工作

本节的范例是在Eclipse IDE里完成的。无论你使用Eclipse还是其它的IDE比如NetBeans,打开这个IDE并且创建一个新的Java工程。

范例实现…

按照接下来的步骤实现本节的范例

1. 首先,我们必须实现用来处理运行时异常的类。这个类实现UncaughtException

Handler接口并且实现这个接口的uncaughtException()方法。我们的范例将使用Exception

Handler类的uncaughtException()方法打印出异常信息和抛出异常的线程代码。代码如下:

public class ExceptionHandler implements UncaughtExceptionHandler{  
    public void uncaughtException(Thread t, Throwable e) {  
        System.out.printf("An exception has been captured\n");  
        System.out.printf("Thread: %s\n",t.getId());  
        System.out.printf("Exception: %s: %s\n",e.getClass().  
            getName(),e.getMessage());  
        System.out.printf("Stack Trace: \n");  
        e.printStackTrace(System.out);  
        System.out.printf("Thread status: %s\n",t.getState());  
    }  
}

2. 现在,实现一个抛出运行时异常的线程类,命名为Task,它实现了Runnable接口,在实现run()方法时强制抛出运行时异常,例如,把一个String值转换成int值。

public class Task implements Runnable {  
    @Override  
    public void run() {  
        int numero=Integer.parseInt("TTT");  
    }  
}

3.现在实现范例的主程序。实现一个包含main()方法的Main类,创建一个Task对象,并用它作为传入参数来创建一个Thread对象。并调用setUncaughtExceptionHandler()方法设置线程的运行时异常处理器,然后启动这个线程

public class Main {  
    public static void main(String[] args) { 
				Task task=new Task();  
        Thread thread=new Thread(task);  
        thread.setUncaughtExceptionHandler(new ExceptionHandler());  
        thread.start();  
    }  
}

4. 运行范例并查看运行结果。


工作原理:


下面的截屏记录了范例的运行结果。当异常抛出并被异常处理器捕获后,将在控制台打印出异常信息和抛出异常的线程代码。参考下面的截屏:

当一个线程抛出了异常并且没有被捕获时(这种情况只可能是运行时异常),JVM检查这个线程是否被预置了未捕获异常处理器。如果找到,JVM将调用线程对象的这个方法,并将这个线程对象和异常作为传入参数。

如果线程没有被预置未捕获异常处理器,JVM将打印堆栈记录到控制台,并退出程序。

更多信息:

Thread类还有另一个方法可以处理未捕获到的异常,即静态方法setDefaultUncaughtExceptionHandler()。这个方法在应用程序中为所有的线程对象创建了一个异常处理器。当线程抛出一个未捕获到的异常时,JVM将为异常寻找以下三种可能的处理器。

首先,它查找线程对象的未捕获异常处理器。如果找不到,JVM继续查找线程对象所在的线程组(ThreadGroup)的未捕获异常处理器,这将在“线程组中不可控异常的处理”一节中讲解。如果还是找不到,如同本节所讲的,JVM将继续查找默认的未捕获异常处理器。

如果没有一个处理器存在,JVM将堆栈异常记录打印到控制台,并退出程序。