【并发编程】- 线程池使用execute方法自定义异常处理

80 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第13天,点击查看活动详情

  1. execute()方法对应的异常也可以被捕获

    运行类代码如下:

    @Slf4j
    public class ExecuteCatchExceptionRun {
        public static void main(String[] args) {
            ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,3,10, TimeUnit.SECONDS,new LinkedBlockingQueue<Runnable>());
            threadPoolExecutor.setThreadFactory(new ThreadFactory() {
                @Override
                public Thread newThread(Runnable r) {
                    Thread thread = new Thread(r);
                    thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler () {
                        @Override
                        public void uncaughtException(Thread t, Throwable e) {
                            log.info("执行execute()方法通过使用自定义ThreadFactory也能捕获异常");
                            e.printStackTrace();
                        }
                    });
                    return thread;
                }
            });
    
            threadPoolExecutor.execute(new Runnable() {
                @Override
                public void run() {
                    Integer.valueOf("A");
                }
            });
        }
    }
    

    运行结果如下:

    16:49:42.898 [Thread-0] INFO com.ozx.concurrentprogram.executor.controller.ExecuteCatchExceptionRun - 执行execute()方法通过使用自定义ThreadFactory也能捕获异常

    java.lang.NumberFormatException: For input string: "A" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.valueOf(Integer.java:766) at com.ozx.concurrentprogram.executor.controller.ExecuteCatchExceptionRun2.run(ExecuteCatchExceptionRun.java:39)atjava.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)atjava.util.concurrent.ThreadPoolExecutor2.run(ExecuteCatchExceptionRun.java:39) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutorWorker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)

    从运行结果看出线程池执行execute()方法原来不能捕获异常,直接输出堆栈信息,但是可以通过自定义ThreadFactory的方式进行捕获异常。

Future的缺点

​ 接口Future的实现类是FutureTask.java,而且在使用线程池时,默认情况下也是使用FutureTask.java类作为接口Future的实现类,简单说就是如果使用Future与Callable的使用情况下,使用Future接口也就是在使用FutureTask.java实现类。

​ Callable接口与Runnable接口的最大优点如下:

  • Callable接口可以通过Future取得返回值。

    但是Future接口调用get()方法取得处理的返回值时是阻塞的,简单就是如果调用Future对象的get()方法时,任务暂时未执行完成,那么调用get()方法时会一直阻塞到这任务完成时为止。如果是这样的情况,前面的任务一旦耗时比较久,则后来的任务调用get()方法也会呈现阻塞状态,就是排队进行等待,大大影响运行效率,就是Future的缺点,主线程无法保证获得的是最先完成任务的返回值。