6 Star 72 Fork 28

JustryDeng / notebook

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
[03]捕获异步线程异常的常用方式.md 13.61 KB
一键复制 编辑 原始数据 按行查看 历史

捕获异步线程异常的常用方式


声明 捕获异步线程异常的方式有很多,本文只介绍(并示例)几种相对常用的方式。

捕获异步线程异常的常用方式(结论)

开启线程的方式 使用线程池的情况 捕获异步线程异常的常用方式
Thread 不使用线程池 1. Thread.setDefaultUncaughtExceptionHandler设置默认的线程异常处理器。
2. Thread实例.setUncaughtExceptionHandler给当指定线程设置线程异常处理器。
Thread 使用线程池ExecutorService#execute 1. Thread.setDefaultUncaughtExceptionHandler设置默认的线程异常处理器。
2. 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常。
3. 自定义ThreadFactory, 重写newThread方法,给线程工厂生产出来的Thread实例设置UncaughtExceptionHandler
Thread 使用线程池ExecutorService#submit 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常。
Runnable 不使用线程池 1. Thread.setDefaultUncaughtExceptionHandler设置默认的线程异常处理器。
2. Thread实例.setUncaughtExceptionHandler给当指定线程设置线程异常处理器。
Runnable 使用线程池ExecutorService#execute 1. Thread.setDefaultUncaughtExceptionHandler设置默认的线程异常处理器。
2. 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常。
3. 自定义ThreadFactory, 重写newThread方法,给线程工厂生产出来的Thread实例设置UncaughtExceptionHandler
Runnable 使用线程池ExecutorService#submit 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常。
Callable 不使用线程池 在使用Future#get()方法获取Callable#call()的返回结果时, try-catch获取异常
注:此方式,若不使用Future#get()获取结果,那么 异步线程的异常信息将会被吞掉。
Callable 使用线程池ExecutorService#submit 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常。

捕获异步线程异常的常用方式(示例说明)

提示 完整测试项目可见文末链接。

准备工作

  • 一个Thread

    在这里插入图片描述

  • 一个Runnable

    在这里插入图片描述

  • 一个Callable

    在这里插入图片描述

  • 一个UncaughtExceptionHandler

    在这里插入图片描述

  • 一个ThreadPoolExecutor

    在这里插入图片描述

  • 一个自定义的ThreadFactory

    在这里插入图片描述

Thread不使用线程池

  • 方式一:Thread#setDefaultUncaughtExceptionHandler
     /**
      * [不使用线程池]方式一: Thread.setDefaultUncaughtExceptionHandler 设置默认的线程异常处理器
      */
     private static void testThread1() {
         Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
         MyThread myThread = new MyThread();
         myThread.start();
     }
  • 方式二:Thread#setUncaughtExceptionHandler
     /**
      * [不使用线程池]方式二: Thread实例.setUncaughtExceptionHandler 给当指定线程设置线程异常处理器
      */
     private static void testThread2() {
         MyThread myThread = new MyThread();
         myThread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
         myThread.start();
     }

Thread使用线程池ExecutorService#execute

  • 方式一:Thread#setDefaultUncaughtExceptionHandler
     /**
      * [使用线程池execute]方式一: Thread.setDefaultUncaughtExceptionHandler 设置默认的线程异常处理器
      */
     private static void testThread3() {
         Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
         ExecutorService executorService = Executors.newFixedThreadPool(3);
         MyThread myThread = new MyThread();
         executorService.execute(myThread);
     }
  • 方式二:自定义ThreadPoolExecutor, 重写afterExecute方法
     /**
      * [使用线程池execute]方式二: 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常
      */
     private static void testThread4() {
         ExecutorService executorService = new MyThreadPoolExecutor(5,
                 50, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20),
                 Thread::new, new ThreadPoolExecutor.AbortPolicy());
         MyThread myThread = new MyThread();
         executorService.execute(myThread);
     }
  • 方式三:自定义ThreadFactory, 给线程工厂生产出来的Thread实例设置UncaughtExceptionHandler
     /**
      * [使用线程池execute]方式三: 自定义ThreadFactory, 重写newThread方法,给线程工厂生
      *                          产出来的Thread实例设置UncaughtExceptionHandler
      */
     private static void testThread5() {
         ExecutorService executorService = new ThreadPoolExecutor(5,
                 50, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20),
                 new MyThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
         MyThread myThread = new MyThread();
         executorService.execute(myThread);
     }

Thread使用线程池ExecutorService#submit

  • 方式:自定义ThreadPoolExecutor, 重写afterExecute方法
     /**
      * [使用线程池submit]方式一: 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常
      */
     private static void testThread6() {
         ExecutorService executorService = new MyThreadPoolExecutor(5,
                 50, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20),
                 Thread::new, new ThreadPoolExecutor.AbortPolicy());
         MyThread myThread = new MyThread();
         executorService.submit(myThread);
     }

Runnable不使用线程池

  • 方式一:Thread#setDefaultUncaughtExceptionHandler
     /**
      * [不使用线程池]方式一: Thread.setDefaultUncaughtExceptionHandler 设置默认的线程异常处理器
      */
     private static void testRunnable1() {
         Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
         MyRunnable myRunnable = new MyRunnable();
         new Thread(myRunnable).start();
     }
  • 方式二:Thread#setUncaughtExceptionHandler
     /**
      * [不使用线程池]方式二: Thread实例.setUncaughtExceptionHandler 给当指定线程设置线程异常处理器
      */
     private static void testRunnable2() {
         MyRunnable myRunnable = new MyRunnable();
         Thread thread = new Thread(myRunnable);
         thread.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
         thread.start();
     }

Runnable使用线程池ExecutorService#execute

  • 方式一:Thread.setDefaultUncaughtExceptionHandler
     /**
      * [使用线程池execute]方式一: Thread.setDefaultUncaughtExceptionHandler 设置默认的线程异常处理器
      */
     private static void testRunnable3() {
         Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
         ExecutorService executorService = Executors.newFixedThreadPool(3);
         MyRunnable myRunnable = new MyRunnable();
         executorService.execute(myRunnable);
     }
  • 方式二:自定义ThreadPoolExecutor, 重写afterExecute方法
     /**
      * [使用线程池execute]方式二: 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常
      */
     private static void testRunnable4() {
         ExecutorService executorService = new MyThreadPoolExecutor(5,
                 50, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20),
                 Thread::new, new ThreadPoolExecutor.AbortPolicy());
         MyRunnable myRunnable = new MyRunnable();
         executorService.execute(myRunnable);
     }
  • 方式三:自定义ThreadFactory, 给线程工厂生产出来的Thread实例设置UncaughtExceptionHandler
     /**
      * [使用线程池execute]方式三: 自定义ThreadFactory, 重写newThread方法,给线程工厂生
      *                          产出来的Thread实例设置UncaughtExceptionHandler
      */
     private static void testRunnable5() {
         ExecutorService executorService = new ThreadPoolExecutor(5,
                 50, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20),
                 new MyThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
         MyRunnable myRunnable = new MyRunnable();
         executorService.execute(myRunnable);
     }

Runnable使用线程池ExecutorService#submit

  • 方式:自定义ThreadPoolExecutor, 重写afterExecute方法
     	/**
     	 * [使用线程池submit]方式一: 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常
     	 */
     	private static void testRunnable6() {
     	    ExecutorService executorService = new MyThreadPoolExecutor(5,
     	            50, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20),
     	            Thread::new, new ThreadPoolExecutor.AbortPolicy());
     	    MyRunnable myRunnable = new MyRunnable();
     	    executorService.submit(myRunnable);
     	}

Callable不使用线程池

  • 方式:在使用Future#get()方法获取Callable#call()的返回结果时, try-catch获取异常
     /**
      * [不使用线程池]: 在使用Future#get()方法获取Callable#call()的返回结果时, try-catch获取异常
      *
      * 注: 此方式, 若不使用Future#get()获取结果,那么 异步线程的异常信息将会被吞掉
      */
     private static void testCallable1() throws InterruptedException {
         MyCallable myCallable = new MyCallable();
         FutureTask<Object> futureTask = new FutureTask<> (myCallable);
         Thread thread = new Thread(futureTask);
         thread.start();
         try {
             // 在尝试获取结果时,捕获异常
             Object o = futureTask.get();
         } catch (ExecutionException e) {
             Throwable cause = e.getCause();
             log.error(" callable-thread occur exception", cause);
         }
     }

Callable使用线程池ExecutorService#submit

  • 方式:自定义ThreadPoolExecutor, 重写afterExecute方法
     /**
      * [使用线程池submit]: 自定义ThreadPoolExecutor, 重写afterExecute方法,在afterExecute方法中感知异常
      */
     private static void testCallable2() {
         ExecutorService executorService = new MyThreadPoolExecutor(5,
                 50, 3, TimeUnit.SECONDS, new LinkedBlockingQueue<>(20),
                 Thread::new, new ThreadPoolExecutor.AbortPolicy());
         MyCallable myCallable = new MyCallable();
         executorService.submit(myCallable);
     }

相关资料

1
https://gitee.com/JustryDeng/notebook.git
git@gitee.com:JustryDeng/notebook.git
JustryDeng
notebook
notebook
master

搜索帮助