9.异常处理之未捕获异常处理(setDefaultUncaughtExceptionHandler 方法、setUncaughtExceptionHandler 方法)

一、未捕获异常

1、概述
  1. 未捕获异常(Uncaught Exception)是指在线程执行过程中抛出的、没有被 try-catch 块捕获的异常

  2. 如果未捕获异常没有被处理,JVM 会调用线程的 UncaughtExceptionHandler 来处理异常

  3. 如果没有显式设置 UncaughtExceptionHandler,JVM 会使用默认的行为,打印异常的堆栈跟踪信息并终止线程

2、注意事项
  1. Java 程序中某个线程抛出未捕获异常并不会导致整个 Java 程序终止,只会终止该线程本身

  2. 其他线程仍然会继续运行,除非所有非守护线程都终止了

3、实例实操
(1)演示案例
// 使用线程池来使程序一直运行
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.execute(() -> {
});

new Thread(() -> {
    int a = 10 / 0;
}, "T1").start();

new Thread(() -> {
    try {
        int a = 10 / 0;
    } catch (Exception e) {
        System.out.println("Caught Exception: " + e.getMessage());
    }
}, "T2").start();
  • 输出结果
Exception in thread "T1" java.lang.ArithmeticException: / by zero
	at com.exception.SetDefaultUncaughtExceptionHandlerTest.lambda$test1$1(SetDefaultUncaughtExceptionHandlerTest.java:19)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caught Exception: / by zero
(3)演示案例分析
  1. 创建了一个单线程的线程池,并向它提交了一个空任务,线程池中的线程会一直保持活动状态

  2. 在 T1 线程中,抛出了一个未捕获的异常,这会导致 T1 线程终止

  3. T2 线程中,捕获了处理了异常,因此,T2 线程不会因为异常而终止,T2 线程会正常执行完毕

  • 此时,1 线程会因为未捕获异常而终止,T2 线程会正常执行完毕,线程池中的线程会一直保持活动状态,因此,Java 程序不会,会继续运行

二、setDefaultUncaughtExceptionHandler 方法

1、概述
  1. 在 Java 中,setDefaultUncaughtExceptionHandler 方法是一个用于设置默认未捕获异常处理器(Default Uncaught Exception Handler)的静态方法

  2. 当线程中发生未捕获的异常时,JVM 会调用该处理器来处理异常,通过设置默认的未捕获异常处理器,可以为所有线程提供一个统一的异常处理机制

2、基本介绍
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
  1. eh 是 Thread.UncaughtExceptionHandler 接口的实现,用于处理未捕获异常

  2. Thread.UncaughtExceptionHandler 是一个函数式接口,它只有一个方法 void uncaughtException(Thread t, Throwable e),其中,t 是发生异常的线程,e 是未捕获的异常对象

3、实例实操
(1)演示案例
// 使用线程池来使程序一直运行
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.execute(() -> {
});

// 设置默认的未捕获异常处理器
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
    System.out.println("Default Uncaught Exception Handler");
    System.out.println("Thread: " + thread.getName());
    System.out.println("Exception: " + throwable.getMessage());
    System.out.println("Stack Trace: ");
    throwable.printStackTrace();
});

new Thread(() -> {
    int a = 10 / 0;
}, "T1").start();

new Thread(() -> {
    try {
        int a = 10 / 0;
    } catch (Exception e) {
        System.out.println("Caught Exception: " + e.getMessage());
    }
}, "T2").start();
  • 输出结果
Default Uncaught Exception Handler
Thread: T1
Caught Exception: / by zero
Exception: / by zero
Stack Trace: 
java.lang.ArithmeticException: / by zero
	at com.exception.SetDefaultUncaughtExceptionHandlerTest.lambda$test2$5(SetDefaultUncaughtExceptionHandlerTest.java:47)
	at java.base/java.lang.Thread.run(Thread.java:833)
(2)演示案例
  1. T1 线程的异常被 Default Uncaught Exception Handler 处理
Default Uncaught Exception Handler
Thread: T1
Exception: / by zero
Stack Trace: 
java.lang.ArithmeticException: / by zero
	at com.exception.SetDefaultUncaughtExceptionHandlerTest.lambda$test2$5(SetDefaultUncaughtExceptionHandlerTest.java:47)
	at java.base/java.lang.Thread.run(Thread.java:833)
  1. T2 线程的异常被 try-catch 块处理
Caught Exception: / by zero

三、setUncaughtExceptionHandler 方法

1、概述
  1. 在 Java 中,setUncaughtExceptionHandler 是 Thread 类的一个方法,用于为线程设置一个 未捕获异常处理器(Uncaught Exception Handler)

  2. 当线程中发生未捕获的异常时,JVM 会调用该处理器来处理异常。

  3. 如果为某个线程单独设置了 UncaughtExceptionHandler,则优先使用该线程的处理器,而不是默认处理器(Default Uncaught Exception Handler)

2、基本介绍
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)
  1. eh 是 Thread.UncaughtExceptionHandler 接口的实现,用于处理未捕获异常

  2. Thread.UncaughtExceptionHandler 是一个函数式接口,它只有一个方法 void uncaughtException(Thread t, Throwable e),其中,t 是发生异常的线程,e 是未捕获的异常对象

3、实例实操
(1)演示案例
// 使用线程池来使程序一直运行
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.execute(() -> {
});

// 设置默认的未捕获异常处理器
Thread.setDefaultUncaughtExceptionHandler((thread, throwable) -> {
    System.out.println("Default Uncaught Exception Handler - Thread: " + thread.getName());
    System.out.println("Default Uncaught Exception Handler - Exception: " + throwable.getMessage());
});

new Thread(() -> {
    int a = 10 / 0;
}, "T1").start();

new Thread(() -> {
    try {
        int a = 10 / 0;
    } catch (Exception e) {
        System.out.println("Caught Exception: " + e.getMessage());
    }
}, "T2").start();

Thread thread3 = new Thread(() -> {
    int a = 10 / 0;
}, "T3");

thread3.setUncaughtExceptionHandler((thread, throwable) -> {
    System.out.println("Custom Uncaught Exception Handler - Thread: " + thread.getName());
    System.out.println("Custom Uncaught Exception Handler - Exception: " + throwable.getMessage());
});

thread3.start();
  • 输出结果
Custom Uncaught Exception Handler - Thread: T3
Caught Exception: / by zero
Default Uncaught Exception Handler - Thread: T1
Custom Uncaught Exception Handler - Exception: / by zero
Default Uncaught Exception Handler - Exception: / by zero
(2)演示案例分析
  1. T1 线程的异常被 Default Uncaught Exception Handler 处理
Default Uncaught Exception Handler - Thread: T1
Default Uncaught Exception Handler - Exception: / by zero
  1. T2 线程的异常被 try-catch 块处理
Caught Exception: / by zero
  1. T3 线程的异常被 Uncaught Exception Handler 处理
Custom Uncaught Exception Handler - Thread: T3
Custom Uncaught Exception Handler - Exception: / by zero
### 回答1: Java 全局异常处理方法包括:采用 try-catch 块来处理异常;使用 try-with-resources 语句来声明资源;使用 finally 块来清理资源;使用 Throwable 类的 printStackTrace()方法来跟踪异常;使用 throw 关键字来抛出异常。 ### 回答2: Java有几种全局异常处理方法。一种常见的方法是使用try-catch语句块来捕捉和处理异常。try块内编写有可能引发异常的代码,当异常发生时,程序会跳转到catch块执行相应的异常处理代码。catch块可以有多个,每个catch块用于处理不同类型的异常。这种方法通常用于局部异常处理,即在特定的代码段中处理异常。 另一种全局异常处理方法是使用Thread类的setDefaultUncaughtExceptionHandler()方法来为所有线程设置一个默认的未捕获异常处理器。这样设置后,应用程序中的所有线程在发生未捕获的异常时都会调用该处理器进行处理。这种方法适用于处理在多线程环境中发生的异常。 此外,还可以通过实现Thread.UncaughtExceptionHandler接口来自定义异常处理器。通过实现接口中的uncaughtException()方法,可以自定义异常处理逻辑,并在发生未捕获的异常时进行处理。然后,通过Thread类的setUncaughtExceptionHandler()方法将自定义异常处理器设置给指定的线程。 综上所述,Java的全局异常处理方法包括使用try-catch语句块进行局部异常处理、使用setDefaultUncaughtExceptionHandler()方法为所有线程设置默认的未捕获异常处理器,以及通过实现Thread.UncaughtExceptionHandler接口来自定义异常处理器。根据具体的应用场景选择合适的方法来处理异常。 ### 回答3: Java的全局异常处理方法主要有以下几种: 1. try-catch语句块:在编写代码时,可以在可能发生异常的地方使用try-catch语句块捕获异常,然后通过catch块处理异常。这种方法适用于局部的、针对特定代码片段的异常处理。 2. throws关键字:可以在方法声明中使用throws关键字来声明可能会抛出的异常,然后在调用该方法时,使用try-catch语句块来捕获这些异常。这种方法适用于方法无法直接处理异常情况的情况下。 3. 自定义异常类:可以通过定义自己的异常类来处理特定的异常情况。通过继承Exception类或RuntimeException类,可以创建自己的异常类,并在需要抛出异常的地方使用throw关键字来抛出。 4. 异常处理器:Java提供了Thread类的setDefaultUncaughtExceptionHandler方法,可以设置默认的异常处理器。通过实现Thread.UncaughtExceptionHandler接口并自定义处理方法,可以在某个线程抛出未捕获的异常时进行处理。 5. AOP(面向切面编程):通过使用AOP技术,可以在代码中定义全局的异常处理切面。在抛出异常时,切面会拦截异常并进行处理。 总的来说,Java全局异常处理方法可以根据不同的场景和需求选择不同的处理方式。最佳实践是在写代码时尽量考虑到可能的异常情况,使用try-catch语句块进行局部异常处理;对于无法直接处理的异常情况,可以使用throws关键字声明异常;对于特定的异常情况,可以定义自己的异常类进行处理;对于全局的异常处理,可以使用异常处理器或AOP技术。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值