线程异常 UncaughtException
线程未捕获异常应该如何处理?
UncaughtException 专门用于处理线程未捕获的异常。能检测出线程未捕获异常而终止的情况。
主线程可以轻松的发现异常,子线程却不行,子线程即使抛出异常,主线程也不受影响。
子线程异常无法用传统方法捕获。
示例:主线程可以轻松的发现异常,子线程却不行,子线程即使抛出异常,主线程也不受影响。
/**
* 描述: 单线程,抛出,处理,有异常堆栈
* 多线程,子线程发生异常,会有什么不同?
* 子线程抛出异常,主线程并不会中断
*
* Exception in thread "Thread-0" java.lang.RuntimeException
* at com.xdclass.couponapp.test.uncaughtexception.ExceptionInChildThread.run(ExceptionInChildThread.java:18)
* 0
* 1
* 2
*/
public class ExceptionInChildThread implements Runnable {
public static void main(String[] args) {
new Thread(new ExceptionInChildThread()).start();
for (int i = 0; i < 1000; i++) {
System.out.println(i);
}
}
@Override
public void run() {
throw new RuntimeException();
}
}
示例:子线程异常无法用传统方法捕获。
package com.xdclass.couponapp.test.uncaughtexception;
/**
* 描述: 1. 不加try catch抛出4个异常,都带线程名字
* 2. 加了try catch,期望捕获到第一个线程的异常,线程234不应该运行,希望看到打印出Caught Exception
* 3. 执行时发现,根本没有Caught Exception,线程1234依然运行并且抛出异常
*
* 说明线程的异常不能用传统方法捕获
*/
public class CantCatchDirectly implements Runnable {
public static void main(String[] args) throws InterruptedException {
try {
new Thread(new CantCatchDirectly(), "MyThread-1").start();
Thread.sleep(300);
new Thread(new CantCatchDirectly(), "MyThread-2").start();
Thread.sleep(300);
new Thread(new CantCatchDirectly(), "MyThread-3").start();
Thread.sleep(300);
new Thread(new CantCatchDirectly(), "MyThread-4").start();
} catch (RuntimeException e) {
System.out.println("Caught Exception.");
}
}
@Override
public void run() {
throw new RuntimeException();
}
}
利用 UncaughtExceptionHandler
- 给程序统一设置
- 给每个线程单独设置
- 给线程池设置
示例:利用 UncaughtExceptionHandler (推荐)
自定义全局异常处理器
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* 描述: 自己的MyUncaughtExceptionHanlder
*/
public class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
private String name;
public MyUncaughtExceptionHandler(String name) {
this.name = name;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
Logger logger = Logger.getAnonymousLogger();
//保存日志……
//报警通知……
logger.log(Level.WARNING, "线程异常,终止啦" + t.getName());
System.out.println(name + " 捕获了异常 " + t.getName() + " 异常");
}
}
使用自定义 Handler 作为全局兜底异常处理
/**
* 描述: 使用刚才自己写的UncaughtExceptionHandler
*/
public class UseOwnUncaughtExceptionHandler implements Runnable {
public static void main(String[] args) throws InterruptedException {
//定义主线程的异常处理器
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler("捕获器1"));
new Thread(new UseOwnUncaughtExceptionHandler(), "MyThread-1").start();
Thread.sleep(300);
new Thread(new UseOwnUncaughtExceptionHandler(), "MyThread-2").start();
Thread.sleep(300);
new Thread(new UseOwnUncaughtExceptionHandler(), "MyThread-3").start();
Thread.sleep(300);
new Thread(new UseOwnUncaughtExceptionHandler(), "MyThread-4").start();
}
@Override
public void run() {
throw new RuntimeException();
}
}
console
三月 03, 2020 9:42:53 下午 com.xdclass.couponapp.test.uncaughtexception.MyUncaughtExceptionHandler uncaughtException
警告: 线程异常,终止啦MyThread-1
捕获器1 捕获了异常 MyThread-1 异常
三月 03, 2020 9:42:53 下午 com.xdclass.couponapp.test.uncaughtexception.MyUncaughtExceptionHandler uncaughtException
警告: 线程异常,终止啦MyThread-2
捕获器1 捕获了异常 MyThread-2 异常
三月 03, 2020 9:42:53 下午 com.xdclass.couponapp.test.uncaughtexception.MyUncaughtExceptionHandler uncaughtException
警告: 线程异常,终止啦MyThread-3
捕获器1 捕获了异常 MyThread-3 异常
三月 03, 2020 9:42:54 下午 com.xdclass.couponapp.test.uncaughtexception.MyUncaughtExceptionHandler uncaughtException
警告: 线程异常,终止啦MyThread-4
捕获器1 捕获了异常 MyThread-4 异常
未捕获异常 UncaughtException