《Java程序员面试秘笈》—— 1.9 线程中不可控异常的处理

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

本节书摘来异步社区《Java 7并发编程实战手册》一书中的第1章,第1.9节,作者:【西】Javier Fernández González,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.9 线程中不可控异常的处理

在Java中有两种异常。

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

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

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

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

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

准备工作
本节的范例是在Eclipse IDE里完成的。无论你使用Eclipse还是其他的IDE(比如NetBeans),都可以打开这个IDE并且创建一个新的Java工程。

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

1.实现用来处理运行时异常的类。这个类实现UncaughtExceptionHandler接口并且实现这个接口的uncaughtException()方法。我们的范例将使用ExceptionHandler类的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类。

public class Main {
  public static void main(String[] args) {```
4.创建一个Task对象,并用它作为传入参数来创建一个Thread对象。接着调用setUncaughtExceptionHandler()方法设置线程的运行时异常处理器,然后启动这个线程。
Task task=new Task();
Thread thread=new Thread(task);
thread.setUncaughtExceptionHandler(new ExceptionHandler());
thread.start();

}
}`
5.运行范例并查看运行结果。

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

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

c2f6ea34446d8cff8c97e724fb106ab9eeba5b3d

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

更多信息
Thread类还有另一个方法可以处理未捕获到的异常,即静态方法setDefaultUncaught ExceptionHandler()。这个方法在应用程序中为所有的线程对象创建了一个异常处理器。

当线程抛出一个未捕获到的异常时,JVM将为异常寻找以下三种可能的处理器。

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

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

相关文章
|
8天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
8天前
|
安全 Java 开发者
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第9天】本文将深入探讨Java并发编程的核心概念,包括线程安全和性能优化。我们将详细解析Java中的同步机制,包括synchronized关键字、Lock接口以及并发集合等,并探讨它们如何影响程序的性能。此外,我们还将讨论Java内存模型,以及它如何影响并发程序的行为。最后,我们将提供一些实用的并发编程技巧和最佳实践,帮助开发者编写出既线程安全又高效的Java程序。
22 3
|
8天前
|
算法 Java 开发者
Java中的多线程编程:概念、实现与性能优化
【4月更文挑战第9天】在Java编程中,多线程是一种强大的工具,它允许开发者创建并发执行的程序,提高系统的响应性和吞吐量。本文将深入探讨Java多线程的核心概念,包括线程的生命周期、线程同步机制以及线程池的使用。接着,我们将展示如何通过继承Thread类和实现Runnable接口来创建线程,并讨论各自的优缺点。此外,文章还将介绍高级主题,如死锁的预防、避免和检测,以及如何使用并发集合和原子变量来提高多线程程序的性能和安全性。最后,我们将提供一些实用的性能优化技巧,帮助开发者编写出更高效、更稳定的多线程应用程序。
|
6天前
|
安全 算法 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第11天】 在Java中,高效的并发编程是提升应用性能和响应能力的关键。本文将探讨Java并发的核心概念,包括线程安全、锁机制、线程池以及并发集合等,同时提供实用的编程技巧和最佳实践,帮助开发者在保证线程安全的前提下,优化程序性能。我们将通过分析常见的并发问题,如竞态条件、死锁,以及如何利用现代Java并发工具来避免这些问题,从而构建更加健壮和高效的多线程应用程序。
|
2天前
|
设计模式 运维 安全
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第15天】在Java开发中,多线程编程是提升应用程序性能和响应能力的关键手段。然而,它伴随着诸多挑战,尤其是在保证线程安全的同时如何避免性能瓶颈。本文将探讨Java并发编程的核心概念,包括同步机制、锁优化、线程池使用以及并发集合等,旨在为开发者提供实用的线程安全策略和性能优化技巧。通过实例分析和最佳实践的分享,我们的目标是帮助读者构建既高效又可靠的多线程应用。
|
3天前
|
Java 程序员 编译器
Java中的线程同步与锁优化策略
【4月更文挑战第14天】在多线程编程中,线程同步是确保数据一致性和程序正确性的关键。Java提供了多种机制来实现线程同步,其中最常用的是synchronized关键字和Lock接口。本文将深入探讨Java中的线程同步问题,并分析如何通过锁优化策略提高程序性能。我们将首先介绍线程同步的基本概念,然后详细讨论synchronized和Lock的使用及优缺点,最后探讨一些锁优化技巧,如锁粗化、锁消除和读写锁等。
|
5天前
|
Java
探秘jstack:解决Java应用线程问题的利器
探秘jstack:解决Java应用线程问题的利器
14 1
探秘jstack:解决Java应用线程问题的利器
|
5天前
|
Java 调度 开发者
Java 21时代的标志:虚拟线程带来的并发编程新境界
Java 21时代的标志:虚拟线程带来的并发编程新境界
14 0
|
7天前
|
监控 安全 Java
深入理解Java并发编程:线程安全与性能优化
【4月更文挑战第10天】 在Java开发中,并发编程是提升应用性能和响应能力的关键手段。然而,线程安全问题和性能调优常常成为开发者面临的挑战。本文将通过分析Java并发模型的核心原理,探讨如何平衡线程安全与系统性能。我们将介绍关键的同步机制,包括synchronized关键字、显式锁(Lock)以及并发集合等,并讨论它们在不同场景下的优势与局限。同时,文章将提供实用的代码示例和性能测试方法,帮助开发者在保证线程安全的前提下,实现高效的并发处理。
|
8天前
|
存储 安全 Java
java多线程之原子操作类
java多线程之原子操作类

热门文章

最新文章