在一个单子项目中使用到了发送邮件业务,因为发送邮件业务是网络请求,会有所延迟,可能达到10ms才请求成功,在前端页面,我们不可能让前端去等待10秒后才告诉执行结果。
其实发送邮件只要配置正确,都是可以执行的,所以无需返回结果。所以我们把发送邮件的相关代码丢到异步中去执行即可。
这样的话,用户一发送验证码,我们判断邮箱号是否正确与否,就可以告诉它发送成功。然后又异步线程池在后台去完成发送邮件的一个操作即可。
- 首先配置线程池
@Configuration
public class ThreadPoolConfig {
@Bean("AsyncTaskExecutor")
public AsyncTaskExecutor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(4);
executor.setQueueCapacity(32);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("task-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
- 配置Service层
@Scope("prototype")
@Service
public class AsyncSendEmailTaskImpl implements IAsyncSendEmailTaskService {
在Sercice实现类上加 @Scope("prototype") 代表此service层是多例模式,这样的话才能用到我们的线程池。
- 配置Service层实现方法
@Override
@Async
public void sendCode(String email) {
todo...
}
这里需要注意的是,要在方法上加在@Async注解才会生效。
4.Controller调用
@Scope("prototype")
@Api(tags = "基础-发送邮件")
@RestController
@RequestMapping
public class SendEmailController {
@Autowired
private IAsyncSendEmailTaskService asyncSendEmailTaskService;
@GetMapping("/sendCode")
@ApiOperation("发送验证码")
public ApiResult sendCode(@RequestParam String email){
asyncSendEmailTaskService.sendCode(email);
return ApiResult.ok("邮件发送成功,10分钟内有效");
}
}
结果对比:
使用单例模式、同步方法耗时:21s
使用多例模式、异步方法耗时:10ms
在计算量大的、耗时久的,不需要立马告诉用户结果的,都可以丢在线程池中去执行,这样增加用户的体验感。