线程异常处理

  • 在run方法上增加异常处理
new Thread(() -> {
    try {
        System.err.println(3 / 2);
        System.err.println(3 / 0);
    } catch (Exception e) {
        System.err.println("Catch exception===>" + e.getMessage());
    }
}).start();
  • 使用UncaughtExceptionHandler处理未捕获异常
Thread thread = new Thread(() -> {
    System.err.println(3 / 2);
    System.err.println(3 / 0);
});
thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.err.println(Thread.currentThread().getName() + "==>" + e.getMessage());
    }
});
thread.start();

可以为所有的Thread设置一个默认的UncaughtExceptionHandler,通过调用Thread.setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)方法

public static void main(String[] args) throws InterruptedException {
    Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
        @Override
        public void uncaughtException(Thread t, Throwable e) {
            System.err.println("全局线程默认异常处理:" + t.getName() + "\n" + e.getMessage());
        }
    });
    new Thread(() -> {
        System.err.println(3 / 0);
    }).start();
    new Thread(() -> {
        System.err.println(args[4]);
    }).start();
}

线程池异常处理

ExecutorService->execute方法线程处理

public class ExecuteCaught
{
    public static void main(String[] args)
    {
        ExecutorService exec = Executors.newCachedThreadPool();
        Thread thread = new Thread(new Task());
        thread.setUncaughtExceptionHandler(new ExceptionHandler());
        exec.execute(thread);
        exec.shutdown();
    }
}
output=====>
1
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
    at com.exception.Task.run(NoCaughtThread.java:25)
    at java.lang.Thread.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

该方式并未捕获异常,正确的处理方法

public class ExecuteCaught
{
    public static void main(String[] args)
    {
        ExecutorService exec = Executors.newCachedThreadPool();
        exec.execute(new ThreadPoolTask());
        exec.shutdown();
    }
}

class ThreadPoolTask implements Runnable
{
    @Override
    public void run()
    {
        Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());
        System.out.println(3/2);
        System.out.println(3/0);
        System.out.println(3/1);
    }
}

注意

只有通过execute提交的任务,才能将它抛出的异常交给UncaughtExceptionHandler,而通过submit提交的任务,无论是抛出的未检测异常还是已检查异常,都将被认为是任务返回状态的一部分。如果一个由submit提交的任务由于抛出了异常而结束,那么这个异常将被Future.get封装在ExecutionException中重新抛出

public static void main(String[] args) throws InterruptedException {
    ExecutorService exec = Executors.newCachedThreadPool();
    exec.submit(() -> {
        System.err.println(3 / 0);
    });
    exec.shutdown();
}
### 未捕获异常

正确方式:

public static void main(String[] args) throws InterruptedException {
    ExecutorService exec = Executors.newCachedThreadPool();
    Future<?> future = exec.submit(() -> {
        System.err.println(3 / 0);
    });
    try {
        Object o = future.get();
    } catch (ExecutionException e) {
        System.err.println("捕获异常:" + e.getMessage());
    }
    exec.shutdown();
}

【知识点】

  1. 如果设置了实例属性uncaughtExceptionHandler(每个线程对象独有),则调用该处理器对未捕获异常进行处理;
  2. 如果没有设置未捕获异常处理器(即1中的uncaughtExceptionHandler),则将线程对象的ThreadGroup当作未捕获异常处理器,在ThreadGroup中获取所以线程对象共享的静态属性defaultUncaughtExceptionHandler来处理未捕获异常(前提是静态的set方法你调用了并且传入处理器实例);
  3. 如果两个set方法都没有调用,那么异常栈信息将被推送到System.err进行处理;

【参考资料】

https://blog.csdn.net/reliveIT/article/details/51167545

results matching ""

    No results matching ""