zoukankan      html  css  js  c++  java
  • 线程的异常捕获与线程池的异常捕获 execute与submit区别

    https://www.cnblogs.com/wscit/p/6100476.html

    #(单线程情况)

    对于单线程来说,只需要重写UncaughtException就好了,如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /**
     * Author: scw
     * Time: 16-11-24
     */
    public class RewriteUncatchtExceptionHandler implements Thread.UncaughtExceptionHandler{
        public void uncaughtException(Thread t, Throwable e) {
            System.out.println("我捕获到了线程池的异常");
        }
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
     * Author: scw
     * Time: 16-11-24
     */
    public class Task implements Runnable {
        public void run() {
            System.out.println("执行任务");
            int num  = Integer.parseInt("TT");
        }
    }
    1
    2
    3
    4
    5
    6
    7
    /**
         * 对于单个线程出现的异常情况可以使用异常处理器,可以捕获到
         */
        public static void catchSingleThread() {
            Task task = new Task();
            Thread thread = new Thread(task);
            thread.setUncaughtExceptionHandler(new RewriteUncatchtExceptionHandler());
         thread.start();
     }

      运行程序,我们发现可以正常的捕获到这个unchecked异常,但是线程池中我们应该怎么处理呢?如下:

    #(线程池)

    首先我们要重写 ThreadFactory来为每个线程实例化的时候创建一个handler

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    /**
     * Author: scw
     * Time: 16-11-24
     */
    public class MyThreadFactory implements ThreadFactory{
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setUncaughtExceptionHandler(new RewriteUncatchtExceptionHandler());
            System.out.println("Thread[" + t.getName() + "] created.");
            return t;
        }
    }

      这个地方还可以setDemon,使线程池内线程皆为守护线程,主线程退出后,强制销毁线程池

    1
    2
    3
    4
    5
    6
    7
    8
    /**
       * 虽然从写ThreadFactory以后,可以捕获到异常,但是只能是execute,而submit还是不行  how to choose one
       */
      public static void catchedExecutor() {
          ExecutorService executorService = Executors.newCachedThreadPool(new MyThreadFactory());
          executorService.execute(new Task());
          executorService.shutdownNow();
      }

      现在问题来了,就是这样虽然可以捕获到异常,但是只能是使用execute的时候可以,使用submit的时候是不成功的,那么我们应该如何选择呢?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /**
     * how to choose submit() or execute()
     * There is a difference concerning exception/error handling.A task queued with execute() that generates some Throwable will cause the UncaughtExceptionHandler
     * for the Thread running the task to be invoked. The default UncaughtExceptionHandler, which typically prints the Throwable stack trace to System.err, will be
     * invoked if no custom handler has been installed.On the other hand, a Throwable generated by a task queued with submit() will bind the Throwable to the Future
     * that was produced from the call to submit(). Calling get() on that Future will throw an ExecutionException with the original Throwable as its cause (accessible
     * by calling getCause() on the ExecutionException).
     * Author: scw
     * Time: 16-11-24
     */

      意思就是说二者最大的区别就是异常处理上,

    在execute的时候,如果你没有实现一个handler,那么他就使用默认的handler来处理异常,你要是实现了一个handler他就会使用的实例化的handler

    除此之外,也可以改写ThreadPoolExecutor.afterExecute()中自定义异常(scheduledexecutorservice两种方式都无效)

    但是对于submit来说,异常是绑定到Future上了,但是调用future.get()的时候,这些异常才会给你抛出来,意味着你自己定义的handler其实是无效的

     

     

    此外,https://segmentfault.com/a/1190000000669942 这篇文章详细了剖析了源码,解释了为什么submit时,异常被吃掉了

    以下是那篇文章的结论:

     

    如果我们关心线程池执行的结果,则需要使用submit来提交task,那么在afterExecute中对异常的处理也需要通过Future接口调用get方法去取结果,才能拿到异常,如果我们不关心这个任务的结果,可以直接使用ExecutorService中的execute方法(实际是继承Executor接口)来直接去执行任务,这样的话,我们的Runnable没有经过多余的封装,在runWorker中得到的异常也直接能在afterExecute中捕捉。好了,以上就是对线程池异常捕捉的一个记录。想想应该不难,今天也是偶然机会看到的。今天在开发中碰到PHP锁的问题,头疼死了。


  • 相关阅读:
    Jmater (十七) 命令行(非GUI)模式详解(二) 执行代理设置
    Jmater (十七) 命令行(非GUI)模式详解(一) 执行、输出结果及日志、简单分步执行脚本
    Jmeter (十六) IF控制器
    Jmeter (十五)用户定义变量&用户参数
    JMeter (十四) Cookie & Session
    Jmeter (十三)调试工具之--HTTP Mirror Server(转载)
    Jmeter (十二)调试工具之--Debug Processor(转载)
    Jmeter (十一)调试工具之--Debug Sampler(转载)
    Jmeter (十)脚本增强_关联
    Shell 变量的截取
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106601.html
Copyright © 2011-2022 走看看