Java多线程:7.线程的异常处理

一、子线程中的异常

  • 在主线程中抛出异常会很容易的被发现,因为程序停止继续向下运行了;而在子线程中抛出异常,主线程会继续执行,异常很难被发现。
/**
 * 在主线程中抛出异常,程序停止继续运行,会有异常堆栈
 * 在子线程中抛出异常,主线程会继续执行,很难发现
 */
public class ThreadExceptions {
     
    public static void main(String[] args) throws InterruptedException {
     
        System.out.println("主线程启动");

        Thread thread = new Thread(new Dowork());
        thread.start();

        Thread.sleep(1000);
        System.out.println("主线程继续执行任务");
    }
}

class Dowork implements Runnable{
     
    @Override
    public void run() {
     
        System.out.println("子线程:"+Thread.currentThread().getName());
        throw new RuntimeException();
    }
}

Java多线程:7.线程的异常处理_第1张图片

  • 子线程中的异常无法用传统的方法(try-catch)捕获
    因为try-catch只能捕获自己线程中的异常。
/**
 * 子线程中的异常无法用传统的方法(try-catch)捕获
 */
public class ThreadExceptions {
     
    public static void main(String[] args) throws InterruptedException {
     
        System.out.println("主线程启动");

        try {
     
            Thread thread = new Thread(new Dowork());
            thread.start();
        }catch (Exception e){
     
            System.out.println("子线程抛出了异常!");
        }

        Thread.sleep(1000);
        System.out.println("主线程继续执行任务");
    }
}

class Dowork implements Runnable{
     
    @Override
    public void run() {
     
        System.out.println("子线程:"+Thread.currentThread().getName());
        throw new RuntimeException();
    }
}

Java多线程:7.线程的异常处理_第2张图片

  • 如果不捕获子线程中的异常,主线程会继续执行,没有人知道发生了异常,会造成意想不到的严重后果。

二、两种捕获子线程异常的解决方案

  • 在每个run()方法中编写try-catch(不推荐
  • 使用UncaughtExceptionHandler(推荐

三、UncaughtExceptionHandler

1.简介
  • UncaughExceptionHandler是Thread类提供的一个异常处理器接口,它能检测到线程因为未捕获异常而终止的情况并进行处理。
  • UncaughtExceptionHandler异常处理器中的内容很简单,就是调用了uncaughtException()方法。
    Java多线程:7.线程的异常处理_第3张图片
  • 异常处理器的调用策略,看一下uncaughtException()的源码
public void uncaughtException(Thread t, Throwable e) {
     
		// 寻找父线程,调用父线程的uncaughtException(),递归
        if (parent != null) {
     
            parent.uncaughtException(t, e);
        } else {
     
    		// 获取线程的默认的异常处理器:
    		// 如果没有使用Thread.setDefaultUncaughtExceptionHandler()设置异常处理器,则取不到
            Thread.UncaughtExceptionHandler ueh =
                Thread.getDefaultUncaughtExceptionHandler();
            if (ueh != null) {
     
            	// 取到了,则执行设置的异常处理器
                ueh.uncaughtException(t, e);
            } else if (!(e instanceof ThreadDeath)) {
     
            	// 没取到,则打印异常信息
                System.err.print("Exception in thread \""
                                 + t.getName() + "\" ");
                e.printStackTrace(System.err);
            }
        }
    }
  • 所有,我们需要实现一个自己的异常处理器,并设置给线程,这样当线程中有异常时,就会走我们自己的异常处理器
2.使用我们自己的异常处理器监控线程中的异常
  • 自己实现异常处理器
/**
 * 自己实现的异常处理器
 */
public class ThreadExceptionHandler implements Thread.UncaughtExceptionHandler{
     
    @Override
    public void uncaughtException(Thread t, Throwable e) {
     
        System.out.println("线程["+t.getName()+"]异常终止:"+e.getMessage());
    }
}
  • 使用异常处理器
public class ThreadExceptions {
     
    public static void main(String[] args) {
     
        System.out.println("主线程开始执行...");
        Thread.setDefaultUncaughtExceptionHandler(new ThreadExceptionHandler());

        Thread thread = new Thread(new DoWorks());
        thread.start();
        Thread thread1 = new Thread(new DoWorks());
        thread1.start();
        Thread thread2 = new Thread(new DoWorks());
        thread2.start();

        System.out.println("主线程继续执行...");
    }
}

class DoWorks implements Runnable{
     
    @Override
    public void run() {
     
        throw new RuntimeException("数据库连接失败了!");
    }
}
  • 效果
    Java多线程:7.线程的异常处理_第4张图片

你可能感兴趣的:(Java多线程,线程异常,线程中异常处理,多线程异常)