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

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


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

开启线程的方式使用线程池的情况捕获异步线程异常的常用方式
Thread不使用线程池1. Thread.setDefaultUncaughtExceptionHandler设置默认的线程异常处理器。
2. Thread实例.setUncaughtExceptionHandler给当指定线程设置线程异常处理器。
Thread使用线程池ExecutorService#execute1. 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#execute1. 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);
    }
    

^_^ 如有不当之处,欢迎指正

^_^ 测试代码托管链接
         https://github.com/JustryDeng…CatchSyncThreadException…

^_^ 本文已经被收录进《程序员成长笔记》 ,笔者JustryDeng

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值