一、什么是异步?
说明:在同步操作中,我们执行到添加数据库的时候,我们必须等待这个方法彻底执行完才能执行“修改数据”,完成后“发送短信”,完成后“发送消息”等操作,如果插入数据库这个动作执行时间较长,下面的流程就需要等待,这就是典型的同步场景。
为了改善上述流程,如果两者或三者关联性不强,能不能将一些非核心业务从主流程中剥离出来,于是有了异步编程Async,改进后的流程如下:
这就是异步Async编程,它是程序并发运行的一种手段,它允许多个事件同时发生,当程序调用需要长时间运行的方法时,它不会阻塞当前的执行流程,程序可以继续运行。并且修改数据、发送短信、发送消息之间可以同步进行,不需要相互等待,也可以使用线程池,实现多线程异步编程。
二、实现方式
2.1、使用 @EnableAsync 启用异步注解
@SpringBootApplication
@EnableAsync
public class StartApplication {
public static void main(String[] args) {
SpringApplication.run(StartApplication.class, args);
}
}
启动类上加@EnableAsync注解,开启异步。
2.2、自定义线程池
//2、自定义defaultThreadPoolExecutor线程池
@Bean(name = "defaultThreadPoolExecutor", destroyMethod = "shutdown")
public ThreadPoolExecutor systemCheckPoolExecutorService() {
return new ThreadPoolExecutor(3,
10,
60,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>(10000),
//置线程名前缀,例如设置前缀为hutool-thread-,则线程名为hutool-thread-1之类。
new ThreadFactoryBuilder().setNamePrefix("default-executor-thread-%d").build(),
(r, executor) -> log.error("system pool is full! "));
}
后面会有一篇文章讲述使用线程池的好处,这里不再介绍。
2.3、方法上加 @Async注解
/**
* 功能描述:发送短信接口
* @Bean(name = "defaultThreadPoolExecutor", destroyMethod = "shutdown")
* @MethodName: sendMsg
* @MethodParam: []
* @Return: void
* @Author: yyalin
* @CreateDate: 2023/4/23 15:02
*/
@Async("defaultThreadPoolExecutor")
public void sendMsg(){
log.info("线程:{},进入发送短信服务中......",Thread.currentThread().getName());
try {
log.info("模拟调用短信接口业务耗时时间.....");
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info("发送短信结束......");
}
在异步处理的方法上添加 @Async ,当对 execute 方法 调用时,通过自定义的线程池 defaultThreadPoolExecutor异步化执行 sendMsg方法。
2.4、执行结果
从图上可以看出,发送消息、发送短信、执行方法都是在主线程下重新启动了一默认线程,各自执行自己的方法,并不需要等待主线程一步一步地完成。
2.5、总结
用 @Async 注解标记的方法,称为异步方法。
1、调用异步方法类上或者启动类加上注解 @EnableAsync;
2、在需要被异步调用的方法外加上 @Async;
3、所使用的 @Async 注解方法的类对象应该是Spring容器管理的bean对象。
更多优秀文章,请扫码关注个人微信公众号或搜索“程序猿小杨”添加