一、未捕获异常
1、概述
-
未捕获异常(Uncaught Exception)是指在线程执行过程中抛出的、没有被
try-catch
块捕获的异常 -
如果未捕获异常没有被处理,JVM 会调用线程的 UncaughtExceptionHandler 来处理异常
-
如果没有显式设置 UncaughtExceptionHandler,JVM 会使用默认的行为,打印异常的堆栈跟踪信息并终止线程
2、注意事项
-
Java 程序中某个线程抛出未捕获异常并不会导致整个 Java 程序终止,只会终止该线程本身
-
其他线程仍然会继续运行,除非所有非守护线程都终止了
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)演示案例分析
-
创建了一个单线程的线程池,并向它提交了一个空任务,线程池中的线程会一直保持活动状态
-
在 T1 线程中,抛出了一个未捕获的异常,这会导致 T1 线程终止
-
T2 线程中,捕获了处理了异常,因此,T2 线程不会因为异常而终止,T2 线程会正常执行完毕
- 此时,1 线程会因为未捕获异常而终止,T2 线程会正常执行完毕,线程池中的线程会一直保持活动状态,因此,Java 程序不会,会继续运行
二、setDefaultUncaughtExceptionHandler 方法
1、概述
-
在 Java 中,setDefaultUncaughtExceptionHandler 方法是一个用于设置默认未捕获异常处理器(Default Uncaught Exception Handler)的静态方法
-
当线程中发生未捕获的异常时,JVM 会调用该处理器来处理异常,通过设置默认的未捕获异常处理器,可以为所有线程提供一个统一的异常处理机制
2、基本介绍
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
-
eh 是
Thread.UncaughtExceptionHandler
接口的实现,用于处理未捕获异常 -
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)演示案例
- 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)
- T2 线程的异常被
try-catch
块处理
Caught Exception: / by zero
三、setUncaughtExceptionHandler 方法
1、概述
-
在 Java 中,setUncaughtExceptionHandler 是 Thread 类的一个方法,用于为线程设置一个 未捕获异常处理器(Uncaught Exception Handler)
-
当线程中发生未捕获的异常时,JVM 会调用该处理器来处理异常。
-
如果为某个线程单独设置了 UncaughtExceptionHandler,则优先使用该线程的处理器,而不是默认处理器(Default Uncaught Exception Handler)
2、基本介绍
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh)
-
eh 是
Thread.UncaughtExceptionHandler
接口的实现,用于处理未捕获异常 -
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)演示案例分析
- T1 线程的异常被 Default Uncaught Exception Handler 处理
Default Uncaught Exception Handler - Thread: T1
Default Uncaught Exception Handler - Exception: / by zero
- T2 线程的异常被
try-catch
块处理
Caught Exception: / by zero
- T3 线程的异常被 Uncaught Exception Handler 处理
Custom Uncaught Exception Handler - Thread: T3
Custom Uncaught Exception Handler - Exception: / by zero