一个try{}catch位置引发的血案

来源:互联网 发布:淘宝企业店铺入驻费用 编辑:程序博客网 时间:2024/04/30 00:44


  多线程是个坑,这话一点不假。最近在使用多线程异步发送邮件的时候就掉坑了。


 老代码如下:


  private static class SendExecutor extends Thread {


public void run() {
init();
if (null != queue) {

                              try {
while (true) {
EmailInfo email = queue.poll(300, TimeUnit.SECONDS);
if (null != email) {
if (log.isInfoEnabled()) {
log.info("send email , targetEmail : " + email.getTargetEmail() + " subject : " + email.getSubject());
}
if (log.isDebugEnabled()) {
log.debug("send email , targetEmail : " + email.getTargetEmail() + " subject : " + email.getSubject() + "  content "
+ email.getContent());
}
sendMail(email.getContent(), email.getSubject(), email.getTargetEmail());
}

                                 }
} catch (Exception e) {
log.error("", e);
}

}
}
}


queue采用的是LinkedBlockingQueue, 粗略的看,是否没有问题(我也是这样的)。 但代码在生产环境上出现了bug。

客户反应,邮件没有接受到. 看日志,代码也没有发现问题。最后在日志中发现了一个错误日志,才提醒了我问题出现的地方。


  问题出现在try{}catch的位置在循环外,因此,如果出现异常,while将跳出,线程将完成,后续就没有消费者执行发送任务。

 查看系统日志发现,因为系统中有部分老用户,老用户的邮箱地址不规范,例如,有一个用户的邮箱地址是 “1”,导致在执行sendMail()的时候,出现异常。

修改这个bug其实也很简单,将try{}catch防止在while里面就行,当然,在进入队列之前,检查邮箱是否为合格的邮箱地址很有必要.


修改后的代码如下:


private static class SendExecutor extends Thread {


public void run() {
init();
if (null != queue) {
while (true) {
try {
EmailInfo email = queue.poll(300, TimeUnit.SECONDS);
if (null != email) {
if (log.isInfoEnabled()) {
log.info("send email , targetEmail : " + email.getTargetEmail() + " subject : " + email.getSubject());
}
if (log.isDebugEnabled()) {
log.debug("send email , targetEmail : " + email.getTargetEmail() + " subject : " + email.getSubject() + "  content "
+ email.getContent());
}
sendMail(email.getContent(), email.getSubject(), email.getTargetEmail());
}
} catch (Exception e) {
log.error("", e);
}
}
}
}
}



0 0