专栏首页IT大咖说SpringBoot线程池的创建、@Async配置步骤及注意事项

SpringBoot线程池的创建、@Async配置步骤及注意事项

前言

最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信。考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了。

但是遇到了许多问题,使得@Async无效,也一直没有找到很好的文章去详细的说明@Async的正确及错误的使用方法及需要注意的地方,这里简单整理了一下遇见的问题,Sring是以配置文件的形式来开启@Async,而SpringBoot则是以注解的方式开启。

我们可以使用springBoot默认的线程池,不过一般我们会自定义线程池(因为比较灵活),配置方式有:

  1. 使用 xml 文件配置的方式
  2. 使用Java代码结合@Configuration进行配置(推荐使用)

下面分别实现两种配置方式

第一步、配置@Async

一、springBoot启动类的配置:

在Spring Boot的主程序中配置@EnableAsync,如下所示:

二、Spring XML的配置方式:

1.applicationContext.xml同目录下创建文件threadPool.xml文件:

2.然后在applicationContext.xml中引入threadPool.xml:<import resource="threadPool.xml" />

第二步:创建两个异步方法的类,如下所示:

第一个类(这里模拟取消订单后发短信,有两个发送短信的方法):

第二个类。调用发短信的方法 (异步方法不能与被调用的异步方法在同一个类中,否则无效):

经过测试得到如下结果:

1.没有使用@Async

2.使用了@Async

可以看出,没有使用@Async方式实现的发送短信是同步执行的,意思就是说第一条发送之后再发送第二条,第二条发送成功之后再给用户提示,这样显然会影响用户体验,再看使用了@Async实现的,在执行第一个发送短信方法之后马上开启另一个线程执行第二个方法,显然这样我们的处理速度回快很多。

使用Java代码结合@Configuration注解的配置方式(推荐使用)

1. 新建一个配置类

package com.boot.common.conf; import java.util.concurrent.ThreadPoolExecutor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; /** * 线程池配置 *@authorzhh * */ @Configuration @EnableAsync public classThreadPoolTaskConfig{ /** * 默认情况下,在创建了线程池后,线程池中的线程数为0,当有任务来之后,就会创建一个线程去执行任务, * 当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中; * 当队列满了,就继续创建线程,当线程数量大于等于maxPoolSize后,开始使用拒绝策略拒绝 */ /** 核心线程数(默认线程数) */ private static final int corePoolSize = 20; /** 最大线程数 */ private static final int maxPoolSize = 100; /** 允许线程空闲时间(单位:默认为秒) */ private static final int keepAliveTime = 10; /** 缓冲队列大小 */ private static final int queueCapacity = 200; /** 线程池名前缀 */ private static final String threadNamePrefix = "Async-Service-"; @Bean("taskExecutor") // bean的名称,默认为首字母小写的方法名 publicThreadPoolTaskExecutortaskExecutor(){ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(corePoolSize); executor.setMaxPoolSize(maxPoolSize); executor.setQueueCapacity(queueCapacity); executor.setKeepAliveSeconds(keepAliveTime); executor.setThreadNamePrefix(threadNamePrefix); // 线程池对拒绝任务的处理策略 // CallerRunsPolicy:由调用线程(提交任务的线程)处理该任务 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 初始化 executor.initialize(); return executor; } }

2.创建两个异步方法的类(和之前的类类似仅仅是方法上注解不一样),如下所示:

第一个类(这里模拟取消订单后发短信,有两个发送短信的方法):

代码中的 @Async("taskExecutor") 对应我们自定义线程池中的 @Bean("taskExecutor") ,表示使用我们自定义的线程池。

第二个类。调用发短信的方法 (异步方法不能与被调用的异步方法在同一个类中,否则无效):

运行截图:

注意看,截图中的 [nio-8090-exec-1] 是Tomcat的线程名称

[Async-Service-1]、[Async-Service-2]表示线程1和线程2 ,是我们自定义的线程池里面的线程名称,我们在配置类里面定义的线程池前缀:

private static final String threadNamePrefix = "Async-Service-"; // 线程池名前缀,说明我们自定义的线程池被使用了。

注意事项

如下方式会使@Async失效

  • 异步方法使用static修饰
  • 异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
  • 异步方法不能与被调用的异步方法在同一个类中
  • 类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
  • 如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解
来源:blog.csdn.net/Muscleheng/article/details/81409672

本文分享自微信公众号 - IT大咖说(itdakashuo),作者:Muscleheng

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-02-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 深入理解currentHashMap

    currentHashMap是线程安全并且高效的一种容器,我们就需要研究一下currentHashMap为什么既能够保证线程安全,又可以保证高效的操作

    IT大咖说
  • Springboot:高并发下耗时操作的实现

    高并发下,就是请求在一个时间点比较多时,很多写的请求打过来时,你的服务器承受很大的压力,当你的一个请求处理时间长时,这些请求将会把你的服务器线程耗尽,即你的主线...

    IT大咖说
  • 两程序员玩“锁”,一人抢救无效身亡

    一般喜欢放在数据库来讲(其实这两个概念是属于计算机的,不要被误导),就说mysql吧,悲观锁,主要是表锁,行锁还有间隙锁,叶锁,读锁,因为这些锁在被触发的时候势...

    IT大咖说
  • 详解 Tomcat 的连接数与线程池

    前言 在使用tomcat时,经常会遇到连接数、线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector)。 在前面的文章 详...

    Java高级架构
  • 干货 | Tomcat 连接数与线程池详解

    在使用tomcat时,经常会遇到连接数、线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector)。

    Java技术栈
  • 优化指南,详解 Tomcat 的连接数与线程池

    在使用tomcat时,经常会遇到连接数、线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector)。

    java思维导图
  • 干货|Tomcat 连接数与线程池详解前言

    在使用tomcat时,经常会遇到连接数、线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector)。

    美的让人心动
  • 详解tomcat的连接数与线程池

    在使用tomcat时,经常会遇到连接数、线程数之类的配置问题,要真正理解这些概念,必须先了解Tomcat的连接器(Connector)。

    小柒2012
  • 线程的阻塞和唤醒

    park方法有两个参数来控制休眠多长时间,第一个参数isAbsolute表示第二个参数是绝对时间还是相对时间,单位是毫秒。

    春哥大魔王
  • Python-线程1.线程2.多线程-threading3.主线程会等待所有的子线程结束后才结束4.查看线程数量 5.threading注意点 6.多线程-共享全局变量 7.列表当做实参传递到线程中

    thread.start_new_thread(function,args[,kwargs])

    意气相许的许

扫码关注云+社区

领取腾讯云代金券