工作中,或多或少都会用到多线程处理问题。今日就遇到一个问题来作为经验留存,内容稍作简单,见解较浅,欢迎留言补充
问题:用户发单之后,发送多条邮件通知
用户在请求一个发单接口之后,需要发送多条邮件通知给目标人。
发单成功返回给客户端一条成功通知:{"code":0,"message":"ok"}
理想状态下是:请求发单成功 ——> 客户端即刻收到成功通知(不必等待邮件发送)
一般邮件发送需要占用一定的时间,导致不能及时吧成功的消息发回给客户端,影响体验。所以需要在发送邮件的方法中,加入异步处理流程。
实现
框架:SpringMVC
一开始,我在发送邮件方法上,加上注解@Async,发现在controller中调用,没有效果public class SendEmailHelper {
private static Logger logger = Logger.getLogger(SendEmailHelper.class);
@Async
public static void send(String title, List toList, String content) {
SendEmailHead head = new SendEmailHead("firefly", "212faef1");
SendEmailBody body = new SendEmailBody();
body.setModel(new SendEmailModel(title, content));
body.setTemplateName("legalNewOrder");
body.setTitle(title);
body.setToList(toList);
try {
XStream xStreamJ = new XStream(new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE);
}
});
String json = xStreamJ.toXML(new SendEmailData(head, body));
logger.info("请求邮件发送数据:" + json);
Thread.sleep(10000); // 模拟时间
logger.info("发送邮件完成");
} catch (Exception e) {
logger.error("法务发单邮件发送失败:" + e.getMessage());
}
}
}
后来查询一些文档, 目前找到两种解决方案,问题解决
注意:以下代码建议使用第一种方案,spring自动维护线程池,第二种方案是每次都会新建一个线程,若想要使用第二种,最好创建一个线程管理来维护线程池来配合使用。
第一种:新建一个线程运行public class SendEmailHelper {
private static Logger logger = Logger.getLogger(SendEmailHelper.class);
public static void send(String title, List toList, String content) {
// 新建线程
new Thread() {
public void run() {
SendEmailHead head = new SendEmailHead("firefly", "212faef1");
SendEmailBody body = new SendEmailBody();
body.setModel(new SendEmailModel(title, content));
body.setTemplateName("legalNewOrder");
body.setTitle(title);
body.setToList(toList);
try {
XStream xStreamJ = new XStream(new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE);
}
});
String json = xStreamJ.toXML(new SendEmailData(head, body));
logger.info("请求邮件发送数据:" + json);
Thread.sleep(10000); // 模拟请求时间
logger.info("发送邮件完成");
} catch (Exception e) {
logger.error("法务发单邮件发送失败:" + e.getMessage());
}
}
}.start();
}
}
第二种方法:使用注解 @Async
把SendEmailHelper,改造成Service,然后使用注解@Async
XML配置
java配置public interface SendEmailService {
void send(String title, List toList, String content);
}
// 实现类
public class SendEmailServiceImpl implements SendEmailService{
private static Logger logger = Logger.getLogger(SendEmailServiceImpl.class);
@Override
@Async
public void send(String title, List toList, String content) {
SendEmailHead head = new SendEmailHead("firefly", "212faef1");
SendEmailBody body = new SendEmailBody();
body.setModel(new SendEmailModel(title, content));
body.setTemplateName("legalNewOrder");
body.setTitle(title);
body.setToList(toList);
try {
XStream xStreamJ = new XStream(new JsonHierarchicalStreamDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new JsonWriter(out, JsonWriter.DROP_ROOT_MODE);
}
});
String json = xStreamJ.toXML(new SendEmailData(head, body));
logger.info("请求邮件发送数据:" + json);
Thread.sleep(10000); // 模拟请求时间
logger.info("发送邮件完成");
} catch (Exception e) {
logger.error("法务发单邮件发送失败:" + e.getMessage());
}
}
}