异步线程注意关注其异常

问题产生

最近优化代码发生了一个bug事件,自测的好好的,部署进入开发环境进行前后端联调时却发生了不可思议的事情,从日志上来看没有任何的异常,但是实体的数据封装却明显不完整。给人的感觉是事情做了一半,但是为什么只做了一半,百思不得其解的情况下,将代码改成了同步处理,取消异步线程。问题立马暴露出来了,原来是空指针在作祟。但这不是重点,重点是探索到这里之后,应该如何应对这样的问题,请见下面代码讲解

问题代码例子

`

public static void main(String[] args) {
    // 创建一个线程池
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0, TimeUnit.SECONDS, new ArrayBlockingQueue<>(20));
    BeanVO beanVO = new BeanVO();
    // 异步设置名称
    Future<?> submit = threadPoolExecutor.submit(new Runnable() {
        @Override
        public void run() {
            setName(beanVO);
        }
    });
    // 异步设置value
    Future<?> submit1 = threadPoolExecutor.submit(new Runnable() {
        @Override
        public void run() {
            setValue(beanVO);
        }
    });
   // 等待所有线程执行完毕
    makeSureAllDone(Lists.newArrayList(submit,submit1));
    System.out.println(beanVO);
}

private static void setValue(BeanVO beanVO) {
    // 来个异常
    int i = 1/0;
    beanVO.setValue("yuan");
}

private static void setName(BeanVO beanVO) {
    beanVO.setName("xiao");
}

static class BeanVO{
    private String name;
    private String value;

     public String getName() {
         return name;
     }

     public void setName(String name) {
         this.name = name;
     }

     public String getValue() {
         return value;
     }

     public void setValue(String value) {
         this.value = value;
     }
 }

public static void makeSureAllDone(List<Future> tasks){
    if(tasks == null || tasks.size() == 0){
        return;
    }
    for (Future task : tasks) {
        try {
            task.get();
        } catch (Exception e) {
            // 重点bug
            continue;
        }
    }
}

`
我们看到以上代码貌似没有什么毛病,异步去设置BeanVO这个对象,是的,但是我们在设置name的时候抛出了异常,这个时候异常已经被吃掉了,为什么了呢?我标出了重点bug,在获取结果的时候,异常这个时候也出现了,只是我们没有管而是单纯的continue。往往在使用线程池的时候,都会被公司简单封装使用,但是封装一旦不注意就是一个难以察觉的bug。
另外出了外部获取get()的时候捕获异常以外,我们的内部代码其实也可以try一次,虽然看起来比较繁杂了些。

Future为什么能获取到异常?什么原理呢?见下篇

posted @ 2022-10-28 16:16  程序媛-肖  阅读(63)  评论(0)    收藏  举报