spirng boot实现异步多线程

shigen坚持更新文章的博客写手,擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长,分享认知,留住感动。 个人IP:shigen

在shigen之前的很多文章中,提到了线程池:

并配有对应的原理图:

在今天重学的时候,遇到了这样的问题:准备去封装一个线程池的,看到了异步线程池的概念。什么?异步线程池,重新复习了一下。意外收获了一个注解Async。

首先,理解一下异步的概念:异步是指进程不需要一直等待下去,而是继续执行下面的操作,不管其他进程的状态。能联系到的最佳的场景是:我要下载文件,文件要能生成很长的时间,不能一直等待对吧。在我的文章《高性能API设计》中就提到了异步思想。

OK,那就直接上代码吧。

简单的controller、service:

typescript 复制代码
   @GetMapping(value = "download")
   public String download() {
     log.info("开始下载-------");
     testService.downloadFile();
     log.info("下载完成-------");
     return "download";
   }
 ​
   @SneakyThrows
   public void downloadFile() {
       log.info("开始-------");
       Thread.sleep(10*1000);
       log.info("结束-------");
   }

相信很多人都是这样写的,那再好的服务器,找个借口的响应时间都是10s+。是的,另一端的用户就准备好台词在心里骂设计者100遍了。

一次请求就是一个线程,这个线程一直在耗时的文件下载阶段,能不阻塞才怪。现在,优化点在于实现文件导出的异步。

看代码:

定义线程池配置类

写烂了,直接复制粘贴。

scss 复制代码
 @Configuration
 public class AsyncConfig {
 ​
     @Bean("asyncExecutor")
     public Executor asyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         // 核心线程数:线程池创建时候初始化的线程数
         executor.setCorePoolSize(10);
         // 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
         executor.setMaxPoolSize(20);
         // 缓冲队列:用来缓冲执行任务的队列
         executor.setQueueCapacity(500);
         // 允许线程的空闲时间60秒:当超过了核心线程之外的线程在空闲时间到达之后会被销毁
         executor.setKeepAliveSeconds(60);
         // 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
         executor.setThreadNamePrefix("async-shigen-");
         // 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程)
         executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
         executor.initialize();
         return executor;
     }
 }

没啥好说的,就是线程的名字带了shigen,便于区分。

主配置类

加上注解EnableAsync即可。

less 复制代码
 @SpringBootApplication
 @EnableAsync
 @MapperScan(basePackages = "com.shigen.demo.dao")
 public class DemoApplication {
 ​
     public static void main(String[] args) {
         SpringApplication.run(DemoApplication.class, args);
     }
 ​
 }

实现类

实现类用的时候就需要线程池了。

less 复制代码
 @Service("testService")
 @Slf4j
 public class TestServiceImpl {
 ​
     /**
      * 不能和调用方放在同一个类中
      * <a href="https://blog.csdn.net/weixin_45151960/article/details/133988933">参考文章</a>
      */
     @SneakyThrows
     @Async("asyncExecutor")
     public void downloadFile() {
         log.info("开始-------");
         Thread.sleep(10*1000);
         log.info("结束-------");
     }
 ​
 }

代码中已经注明:异步方法不能和调用方放在同一个类中。

参考文章:

测试

本来需要10s+的响应时间,现在已经是不到1s了。输出的日志如下:

表明文件的下载在单独的处理。

最后总结一下参考的博客中的几种场景:

场景 API
异步非阻塞无返回值 EnableAsync Async
异步非阻塞又返回值 场景不存在
异步阻塞无返回值 CountDownLatch Async
异步阻塞又返回值 CompletableFuture Async

与shigen一起,每天不一样!

相关推荐
行百里er4 小时前
Redis 完结篇——Redis 热点问题在 Spring Boot 项目中实战
redis·后端
高频因子挖掘机5 小时前
只取最近 60 个交易日,却每次拉全历史:量化脚本变慢的原因与改法
后端·github·api
孟健6 小时前
从5000亿Token到83%字节匹配:AI逆向工程与重构的工程闭环实践
后端·架构·ai编程
码事漫谈7 小时前
丢得静悄悄,谈一谈 Agent 的记忆是怎么没的
后端
迪飞特科技7 小时前
智慧物业平台实战:Spring Boot 整合小程序实现报修巡检费用全流程
spring boot·后端·小程序
考虑考虑7 小时前
@JsonInclude注解使用
spring boot·后端·spring
IT_陈寒7 小时前
Vite的这个问题坑了我三天,原来如此解决!
前端·人工智能·后端
网易云信7 小时前
大模型能上岗做销售吗?我们让 12 款国产模型交了 420 份作业
前端·后端
CCblandy7 小时前
HTTP 长连接 3 类故障实测:[WinError 10053]、99 个 TIME_WAIT、69 次多余握手,4 种对策怎么选
后端·python·网络协议·http·云原生·性能优化·架构
蜗牛互联网8 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python