异步任务在很多地方都用的特别多,例如注册发送邮件,发送短信等等。本文是讲解一个简单的 SpringBoot 异步任务的实现,技术总是慢慢进步的啦。
(狗头保命)👩💻
很喜欢一句话:”八小时内谋生活,八小时外谋发展“
我们:"待别日相见时,都已有所成”😁
校园一角
一、前言
1)概述:
“异步”(Asynchronous)与“同步”(Synchronous)相对,异步不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。也就是说,异步永远是非阻塞的(non-blocking)。
异步操作的程序,在代码执行时,不等待异步调用的语句返回结果就执行后面的程序。当任务间没有先后顺序依赖逻辑的时候,可以使用异步。
同步就是串行。在这里举个注册发送邮件的例子:
同步:
发送注册请求-->注册成功-->执行发送邮件方法--->发送成功-->返回信息前端。
异步:
2)使用场景:
使用到异步任务的地方非常多。
就例如:
注册发送邮件,发送短信
App 消息推送
节省运维凌晨发布任务时间提供效率
二、代码实现
案例:注册发送邮件
1、步骤:
新建 SpringBoot 项目
导入依赖
书写配置
编码
启动测试
2、导入依赖:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-mail</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency></dependencies>
复制代码
3、yml 配置文件
server: port: 8087spring: application: name: springboot-scheduled mail: # 配置 SMTP 服务器地址 host: smtp.qq.com # 发送者邮箱 username: xxxx@qq.com # 配置密码,注意不是真正的密码,而是刚刚申请到的授权码 password: xxxxx # 端口号465或587 port: 587 # 默认的邮件编码为UTF-8 default-encoding: UTF-8 # 配置SSL 加密工厂 properties: mail: smtp: socketFactoryClass: javax.net.ssl.SSLSocketFactory #表示开启 DEBUG 模式,这样,邮件发送过程的日志会在控制台打印出来,方便排查错误 debug: true
复制代码
4、config 层
ThreadPoolTaskExecutorConfig 线程池配置
@Configuration@EnableAsync // 开启异步配置public class ThreadPoolTaskExecutorConfig {
@Bean public TaskExecutor taskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //设置核心线程数 executor.setCorePoolSize(10); //设置最大线程数 executor.setMaxPoolSize(20); //缓冲队列200:用来缓冲执行任务的队列 executor.setQueueCapacity(200); //线程活路时间 60 秒 executor.setKeepAliveSeconds(60); //线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池 executor.setThreadNamePrefix("taskExecutor-"); //设置拒绝策略 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); executor.setWaitForTasksToCompleteOnShutdown(true); return executor; }}
复制代码
5、实体类
@Data@Accessors(chain = true)public class Account { private String username; private String password; private String email;}
复制代码
6、service 层
public interface EmailService { /**用于注册成功后发送邮件 @param account 账号信息*/ void senderEmail(Account account);}
@Slf4j@Servicepublic class EmailServiceImpl implements EmailService { @Autowired private JavaMailSender javaMailSender;
@Async("taskExecutor") @Override public void senderEmail(Account account) { log.info(Thread.currentThread().getName()); //一个复杂的邮件 MimeMessage message = this.javaMailSender.createMimeMessage(); try { //组装 MimeMessageHelper helper = new MimeMessageHelper(message, true); //正文 //主题 helper.setSubject("小可爱,欢迎你的到来哦!!!"); //开启html模式 helper.setText("<h1>小可爱,我想你一定会喜欢这里吧!!!</h1>" + "<p>你的账号为:"+account.getUsername()+"</p>" + "<p>你的密码为:"+account.getPassword()+"</p>", true); //附件 helper.addAttachment("1.jpg", new File("C:\\Users\\ASUS\\Desktop\\杂七杂八\\杂图\\2.gif")); helper.setTo(account.getEmail()); helper.setFrom("790933839@qq.com"); javaMailSender.send(message); } catch (MessagingException e) { e.printStackTrace(); } }}
复制代码
7、controller
@Slf4j@RestController@RequestMapping("/async")public class AsyncController {
private static List<Account> accountList=new ArrayList<Account>();
@Autowired private TaskExecutor taskExecutor;
@Autowired private EmailService emailService;
/**写一个注册发送邮件的栗子 */ @PostMapping("/register") public String register(@RequestBody Account account){ accountList.add(account); emailService.senderEmail(account); log.info(Thread.currentThread().getName()); return "OK"; }}
复制代码
8、测试
我们可以看到在执行发送邮件方法时,并非是主线程在执行,而是从线程池中拉了一个线程来执行,做到了异步操作。
三、自言自语
一个小小的 Demo,不足之处,请见谅!
你好,我是博主宁在春😁
如果你看到这篇文章,并且觉得对你有益的话,就给个赞吧,让我感受一下分享的喜悦吧,蟹蟹。🤗
如若有写的有误的地方,也请大家不啬赐教!!
同样如若有存在疑惑的地方,请留言或私信,定会在第一时间回复你。
持续更新中
评论