异步线程注意关注其异常
问题产生
最近优化代码发生了一个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为什么能获取到异常?什么原理呢?见下篇
本文来自博客园,作者:程序媛-肖,转载请注明原文链接:https://www.cnblogs.com/little-xiao/p/16836466.html
浙公网安备 33010602011771号