多线程中的未捕获异常处理方案。

在多线程中,如果线程的执行代码中出现异常,应该怎么处理?是抛出异常还是在执行代码中直接try catch了?我想一切的一切先从下面的这个demo说起。

package com.coderman.uncatchexception;

import java.util.logging.Logger;

/**
 * 处理子线程的异常
 * @Author zhangyukang
 * @Date 2020/6/27 12:04
 * @Version 1.0
 **/
public class ChildThreadException {
    public static void main(String[] args) {
        ChildThread childThread = new ChildThread();
        try {
            new Thread(childThread,"线程1").start();
        } catch (Exception e) {
            System.out.println("catch 线程1的异常");
        }
        try {
            new Thread(childThread,"线程2").start();
        } catch (Exception e) {
            System.out.println("catch 线程2的异常");
        }
        try {
            new Thread(childThread,"线程3").start();
        } catch (Exception e) {
            System.out.println("catch 线程3的异常");
        }
    }
}

class ChildThread implements Runnable{
    @Override
    public void run() {
        throw new RuntimeException(Thread.currentThread().getName()+"线程出现异常了!");
    }
}

输出结果如下: 可以看到try-catch 似乎没有作用

Exception in thread "线程2" Exception in thread "线程1" java.lang.RuntimeException: 线程1线程出现异常了!
	at com.coderman.uncatchexception.ChildThread.run(ChildThreadException.java:35)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "线程3" java.lang.RuntimeException: 线程3线程出现异常了!
	at com.coderman.uncatchexception.ChildThread.run(ChildThreadException.java:35)
	at java.lang.Thread.run(Thread.java:748)
java.lang.RuntimeException: 线程2线程出现异常了!
	at com.coderman.uncatchexception.ChildThread.run(ChildThreadException.java:35)
	at java.lang.Thread.run(Thread.java:748)

原因是java中try-catch只能捕捉到当前线程的异常,那么上面的try-catch知道保证在主线程启动的时候不出现异常就可以了。

那么问题来了,如何捕捉到子线程的异常信息呢

  • 方式一

在run方法中就处理线程,这种方法有个弊端,如果线程中的逻辑较为复杂,如果我们遗漏了一些异常,那么他依旧会向上抛出。

package com.coderman.uncatchexception;

/**
 * 在子线程中处理线程异常: 不推荐使用如果子线程的逻辑复杂很难捕捉到全部的异常
 *
 * @Author zhangyukang
 * @Date 2020/6/30 10:25
 * @Version 1.0
 **/
public class ChildThreadExceptionCatch {
    public static void main(String[] args) {
        ChildThread2 childThread = new ChildThread2();
        new Thread(childThread, "线程1").start();
        new Thread(childThread, "线程2").start();
        new Thread(childThread, "线程3").start();
    }
}

class ChildThread2 implements Runnable {

    @Override
    public void run() {
        try {
            throw new RuntimeException("出现异常了");
        } catch (RuntimeException e) {
            System.out.println(Thread.currentThread().getName() + "catch 到异常:" + e.getMessage());
        }
    }
}

输入结果:没毛病。

线程1catch 到异常:出现异常了
线程2catch 到异常:出现异常了
线程3catch 到异常:出现异常了
  • 方式二

Thead确实已经提供了一个setUncaughtExceptionHandler方法,我们只需要将自定义未捕获异常处理器作为参数传入进入就可以了。

package com.coderman.uncatchexception;

/**
 * 自定义异常全局处理
 * @Author zhangyukang
 * @Date 2020/6/30 10:32
 * @Version 1.0
 **/
public class MyUncaughtExceptionHandlerImpl implements Thread.UncaughtExceptionHandler {

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println("全局异常捕捉到了异常 ,线程:"+t.getName()+" 异常信息:"+e.getMessage());//这里可以写一下报警代码等
    }
}

package com.coderman.uncatchexception;

import com.sun.org.apache.bcel.internal.generic.NEW;

/**
 * 通过全局异常处理捕捉异常
 * @Author zhangyukang
 * @Date 2020/6/30 10:35
 * @Version 1.0
 **/
public class ChildThreadExceptionCatchByHandler {
    public static void main(String[] args) {
        MyUncaughtExceptionHandlerImpl myUncaughtExceptionHandler = new MyUncaughtExceptionHandlerImpl();
        ChildThread3 childThread3 = new ChildThread3();

        Thread thread = new Thread(childThread3, "线程一");
        Thread thread1 = new Thread(childThread3, "线程二");
        Thread thread2 = new Thread(childThread3, "线程三");

        //启动线程
        thread.start();
        thread1.start();
        thread2.start();
        //设置每个线程对应的全局异常捕捉器

        thread.setUncaughtExceptionHandler(myUncaughtExceptionHandler);
        thread1.setUncaughtExceptionHandler(myUncaughtExceptionHandler);
        thread2.setUncaughtExceptionHandler(myUncaughtExceptionHandler);
    }
}
class ChildThread3 implements Runnable{
    @Override
    public void run() {
        throw new RuntimeException("出现了黑客攻击异常");
    }
}

输出结果

全局异常捕捉到了异常 ,线程:线程一 异常信息:出现了黑客攻击异常
全局异常捕捉到了异常 ,线程:线程二 异常信息:出现了黑客攻击异常
全局异常捕捉到了异常 ,线程:线程三 异常信息:出现了黑客攻击异常
# Java  

评论

公众号:mumuser

企鹅群:932154986

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×