清单 6. LoggingWindow 的定义
import java.awt.*;
import javax.Swing.*;
public class LoggingWindow extends JFrame {
private JTextArea textArea;
public LoggingWindow(String title, final int width,
final int height) {
super(title);
EventQueue.invokeLater(new Runnable() {
public void run() {
setSize(width, height);
textArea = new JTextArea();
JScrollPane pane = new JScrollPane(textArea);
textArea.setEditable(false);
getContentPane().add(pane);
setVisible(true);
}
});
}
public void addLogInfo(final String data) {
EventQueue.invokeLater(new Runnable() {
public void run() {
textArea.append(data);
}
});
}
}
发生运行时异常时,可能要做许多工作来更改发生的问题。该代码的大部分都是 Logging Handler,但是,要执行更改,就必须细分 ThreadGroup ,重写 uncaughtException() ,然后在该线程组中执行您的线程。不过,让我们通过只安装 Thread.UncaughtExceptionHandler ,来看一看 Tiger 的处理方式。
使用 UncaughtExceptionHandler 的定制行为
对于 Tiger, Thread 类定义中添加了一个新的公共内部类 UncaughtExceptionHandler ,更完整的名称为 Thread.UncaughtExceptionHandler (其他类访问内部类时需要使用完整名称)。接口的定义是一个方法,如 7 中所示:
清单 7. UncaughtExceptionHandler 的定义
public interface Thread.UncaughtExceptionHandler {
public void uncaughtException(Thread, Throwable);
}
您可能没有注意到,清单 7 中的方法与我们前面重写的 ThreadGroup 的方法相同。实际上,现在由 ThreadGroup 类实现该接口。
新的内部类可以帮助我们了解下列两对新方法,并有助于我们在 Thread 中使用它们:
getUncaughtExceptionHandler() 和 setUncaughtExceptionHandler() 。
getDefaultUncaughtExceptionHandler() 和 setDefaultUncaughtExceptionHandler() 。
第一对方法是 getUncaughtExceptionHandler() 和 setUncaughtExceptionHandler() ,它们允许您为当前线程及其后代定制行为,从而允许二十或更多的线程拥有自己的定制行为。不过,您更可能使用第二对方法 getDefaultUncaughtExceptionHandler() 和 setDefaultUncaughtExceptionHandler() 。如果使用第二对方法设置默认处理程序,那么没有自己的异常处理程序的所有线程都将使用默认处理程序。
听起来好像很简单。为了进行说明,清单 8 转换了 清单 3 中的 ThreadGroup 友好的程序,使用新的 UncaughtExceptionHandler 接口:
清单 8. UncaughtExceptionHandler 示例
public class HandlerDump {
public static void main(String args[]) throws Exception {
Thread.UncaughtExceptionHandler handler =
new LoggingThreadGroup("Logger");
Thread.currentThread().setUncaughtExceptionHandler(handler);
System.out.println(1 / 0);
}
}
该程序只是将 LoggingThreadGroup 重用为 UncaughtExceptionHandler ,并没有创建新的处理程序实现。请注意,与原来的代码相比,新代码要简洁得多。
其他线程更改
Thread 类不仅支持使用 Tiger 添加的未捕获异常处理程序,它还支持使用 getAllStackTraces() 获得所有有效线程的堆栈跟踪,或者支持使用 getStackTrace() 来只获得当前线程的堆栈跟踪。这两种堆栈跟踪都返回类型为 java.lang.StackTraceElement 的对象, java.lang.StackTraceElement 是 Java 1.4 平台中添加的一个类,它可以让您生成自己的堆栈跟踪。同时,Java 5 平台新添加的功能是一个惟一线程标识符(可以使用 getId() 获得该标识符)和一个新的 Thread.State 类,以及与该类相关的 getThreadState() 方法。最后一个线程更改是一个状态枚举表,该表是用来监视系统状态,而不是用来同步状态的。
结束语
像添加未捕获的异常处理程序这样的简单库更改,可以极大地增加原代码的可理解性。虽然在线程组级别上,新的库代码的功能与原来库代码的相同,但新模型中的易用性和灵活性远远超出了将代码调整为更新的方式所需的时间。当然,老方法仍然可以使用,但最好将代码更新为最新的库功能。