Spring及SpringBoot @Async配置步骤及注意事项
- 前言
最近在做一个用户反馈的功能,就是当用户反馈意见或建议后服务端将意见保存然后发邮件给相关模块的开发者。考虑发邮件耗时的情况所以我想用异步的方法去执行,于是就开始研究Spring的@Async了。但网上的许多教程都是相互抄袭且直接复制代码的,根本没有去自己实践或者更改代码,所以在这两天我遇到了许多问题,使得@Async无效,也一直没有找到很好的文章去详细的说明@Async的正确及错误的使用方法及需要注意的地方,这里Sring是以配置文件的形式来开启@Async,而SpringBoot则是以注解的方式开启。 - 教程
- Spring配置文件
配置文件的话有两种方式一种是精简式:
直接在applicationContext.xml中加入开启异步并添加task的命名空间
<task:executor id="WhifExecutor" pool-size="10"/> <task:annotation-driven executor="WhifExecutor" />xmlns:task="http://www.springframework.org/schema/task" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd这样好处是简单快速,缺点是线程池配置简单,线程创建不能定时关闭。
所以我推荐下面这种,定义一个线程池,然后引入。其实两种方法原理是一样只不过下面这种只是线程池配置更加详细,线程在空闲后会根据存活时间配置进行关闭。
在applicationContext.xml同目录下创建文件threadPool.xml内容如下,然后在applicationContext.xml中引入threadPool.xml:<import resource="threadPool.xml" />
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd"> <!-- 开启异步,并引入线程池 --> <task:annotation-driven executor="threadPool" /> <!-- 定义线程池 --> <bean id="threadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 核心线程数,默认为1 --> <property name="corePoolSize" value="5" /> <!-- 最大线程数,默认为Integer.MAX_VALUE --> <property name="maxPoolSize" value="20" /> <!-- 队列最大长度,一般需要设置值>=notifyScheduledMainExecutor.maxNum;默认为Integer.MAX_VALUE --> <property name="queueCapacity" value="500" /> <!-- 线程池维护线程所允许的空闲时间,默认为60s --> <property name="keepAliveSeconds" value="30" /> <!-- 完成任务自动关闭 , 默认为false--> <property name="waitForTasksToCompleteOnShutdown" value="true" /> <!-- 核心线程超时退出,默认为false --> <property name="allowCoreThreadTimeOut" value="true" /> <!-- 线程池对拒绝任务(无线程可用)的处理策略,目前只支持AbortPolicy、CallerRunsPolicy;默认为后者 --> <property name="rejectedExecutionHandler"> <!-- AbortPolicy:直接抛出java.util.concurrent.RejectedExecutionException异常 --> <!-- CallerRunsPolicy:主线程直接执行该任务,执行完之后尝试添加下一个任务到线程池中,可以有效降低向线程池内添加任务的速度 --> <!-- DiscardOldestPolicy:抛弃旧的任务、暂不支持;会导致被丢弃的任务无法再次被执行 --> <!-- DiscardPolicy:抛弃当前任务、暂不支持;会导致被丢弃的任务无法再次被执行 --> <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property> </bean> </beans> - SpringBoot则是添加@EnableAsync注解
@EnableAsync @SpringBootApplication @ServletComponentScan @MapperScan("com.cmc.schedule.model.mapper") //配置扫描mapper接口的地址 public class NLPApplication extends SpringBootServletInitializer { //不使用springboot内嵌tomcat启动方式 @Override protected SpringApplicationBuilder configure( SpringApplicationBuilder application) { return application.sources(NLPApplication.class); } public static void main(String[] args) { SpringApplication.run(NLPApplication.class, args); } //默认使用fastjson解析 @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat); fastConverter.setFastJsonConfig(fastJsonConfig); HttpMessageConverter<?> converter = fastConverter; return new HttpMessageConverters(converter); } } - 这一步Spring和SpringBoot都是一样的,创建一个异步方法的类
package com.cmc.tst; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; /** * @Component 注解必须要有,否则无法将此bean注入 * 当然也可以使用其他的注解,只要可以装配就行 * * @author chenmc * @date 2017年9月4日 下午3:38:29 */ @Component public class MyAsync { /** * @Async 表明这是一个异步方法,也就是说当调用这个方法时, * spring会创建一条线程来执行这个方法。 * 注意:不能使用static来修饰此方法,否则@Async无效 * * @author chenmc * @date 2017年9月4日 下午3:34:24 */ @Async public void asyncMethod(){ System.out.println(Thread.currentThread().getName()); } } - 测试调用异步方法,我这里使用的是JUnit4测试
@Autowired MyAsync async; @Test public void test() { System.out.println(Thread.currentThread().getName() + "start"); //MyAsync async = new MyAsync(); //自己new出来的对象@Async将无效,必须要spring注入的 async.asyncMethod(); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "end"); } - 总结
这里总结一下@Async注解无效的可能点
一、异步方法使用static修饰
二、异步类没有使用@Component注解(或其他注解)导致spring无法扫描到异步类
三、测试异步方法不能与异步方法在同一个类中
四、测试类中需要使用@Autowired或@Resource等注解自动注入,不能自己手动new对象
五、如果使用SpringBoot框架必须在启动类中增加@EnableAsync注解
- 结语
spring的@Async真的极大的方便了java的异步(多线程)开发,心里默念三遍:感谢spring!感谢spring!感谢spring!
Spring及SpringBoot @Async配置步骤及注意事项的更多相关文章
- SpringBoot线程池的创建、@Async配置步骤及注意事项
最近在做订单模块,用户购买服务类产品之后,需要进行预约,预约成功之后分别给商家和用户发送提醒短信.考虑发短信耗时的情况所以我想用异步的方法去执行,于是就在网上看见了Spring的@Async了. 但是 ...
- IntelliJ IDEA 2017 MySQL5 绿色版 Spring 4 Mybatis 3 配置步骤详解(二)
前言 继续上一篇安装教程 首先是MySQL绿色版安装之后其他组件安装,如果篇幅较长会分为多篇深入讲解,随笔属于学习笔记诸多错误还望指出 共同学习. MySQL 5.7 绿色版 我本地安装的是 ...
- SpringBoot自定义配置步骤
1. 在yml中填写自定义配置 ly: sms: accessKeyId: # 短信配置 accessKeySecret: signName: xx商城 # 签名名称 verifyCodeTempla ...
- 整合struts2+hibernate详细配置步骤及注意事项
刚刚学完这两个框架,就迫不及待的做了一个例子,在整合两个框架的时候,也碰到了一些小问题,下面介绍一下配置的步骤: 1.创建一个自定义的struts2和hibernate的类库 因为之前写例子都是直接将 ...
- spring-boot @Async 的使用、自定义Executor的配置方法
1. TaskExecutor Spring异步线程池的接口类,其实质是java.util.concurrent.Executor Spring 已经实现的异常线程池: 1. SimpleAsyncT ...
- spring boot使用自定义配置的线程池执行Async异步任务
一.增加配置属性类 package com.chhliu.springboot.async.configuration; import org.springframework.boot.context ...
- SpringBoot 自动配置:Spring Data JPA
前言 不知道从啥时候开始项目上就一直用MyBatis,其实我个人更新JPA些,因为JPA看起来OO的思想更强烈些,所以这才最近把JPA拿出来再看一看,使用起来也很简单,除了定义Entity实体外,声明 ...
- spring基于xml的声明式事务控制配置步骤
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- SpringBoot 优雅配置跨域多种方式及Spring Security跨域访问配置的坑
前言 最近在做项目的时候,基于前后端分离的权限管理系统,后台使用 Spring Security 作为权限控制管理, 然后在前端接口访问时候涉及到跨域,但我怎么配置跨域也没有生效,这里有一个坑,在使用 ...
随机推荐
- shell中使用带密码的方式直接pg_dump和psql
数据导出 pg_dump "host=XX.XX.XX.XX port=5432 user=XXXX password=XXXX dbname=XXXXX" -t table_na ...
- html_javascript
js:放在bady标签的底部,保证页面加载完成后才加载js js注释:// 单行注释 /*多行注释*/ js有两种存在形式: 以文件的形式存在,使用时引用在head标签里<script src= ...
- hashTabel List 和 dic
hashTabel List 和 dic 原:https://www.cnblogs.com/jilodream/p/4219840.html .Net 中HashTable,HashMap 和 ...
- 如何用 js 获取虚拟键盘高度?(适用所有平台)
原文地址:https://segmentfault.com/a/1190000010693229?utm_source=tag-newest
- HDU 2243考研路茫茫——单词情结 (AC自动机+矩阵快速幂)
背单词,始终是复习英语的重要环节.在荒废了3年大学生涯后,Lele也终于要开始背单词了. 一天,Lele在某本单词书上看到了一个根据词根来背单词的方法.比如"ab",放在单词前一般 ...
- [OC] UIcollectionView 与 UIcollectionViewCell 的使用
UICollectionView @interface ViewController ()<UICollectionViewDelegate,UICollectionViewDataSou ...
- 爬虫之图片懒加载技术及js加密
图片懒加载 图片懒加载概念: 图片懒加载是一种网页优化技术.图片作为一种网络资源,在被请求时也与普通静态资源一样,将占用网络资源,而一次性将整个页面的所有图片加载完,将大大增加页面的首屏加载时间.为了 ...
- echarts中的区域缩放组件dataZoom,主动触发选区缩放点击事件
options设置 toolbox: { // 工具栏 feature: { dataZoom : { // 选时间缩放功能 show : true, // show为true时,才能触发takeGl ...
- hadoop hdfs ha 模式
这是我自己在公司一个搭建公司大数据框架是自己的选项,在配置yarn ha 出现了nodemanager起不来的问题于是我把yarn搭建为普通yarn 如果有人解决 高yarn的nodemanager问 ...
- PHP如何搭建百度Ueditor富文本编辑器
本文为大家分享了PHP搭建百度Ueditor富文本编辑器的方法,供大家参考,具体内容如下 下载UEditor 官网:下载地址 将下载好的文件解压到thinkphp项目中,本文是解压到PUBLIC目录下 ...