异步任务在很多地方都用的特别多,例如注册发送邮件,发送短信等等。本文是讲解一个简单的 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: 8087
spring:
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
@Service
public 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,不足之处,请见谅!
你好,我是博主宁在春
😁
如果你看到这篇文章,并且觉得对你有益的话,就给个赞吧,让我感受一下分享的喜悦吧,蟹蟹。🤗
如若有写的有误的地方,也请大家不啬赐教!!
同样如若有存在疑惑的地方,请留言或私信,定会在第一时间回复你。
持续更新中
评论