Spring Boot @Async 异步任务执行
1、任务执行和调度
Spring用TaskExecutor和TaskScheduler接口提供了异步执行和调度任务的抽象。
Spring的TaskExecutor和java.util.concurrent.Executor接口时一样的,这个接口只有一个方法execute(Runnable task)。
1.1、TaskExecutor类型
Spring已经内置了许多TaskExecutor的实现,你没有必要自己去实现:
- SimpleAsyncTaskExecutor 这种实现不会重用任何线程,每次调用都会创建一个新的线程。
- SyncTaskExecutor 这种实现不会异步的执行
- ConcurrentTaskExecutor 这种实现是java.util.concurrent.Executor的一个adapter。
- SimpleThreadPoolTaskExecutor 这种实现实际上是Quartz的SimpleThreadPool的一个子类,它监听Spring的声明周期回调。
- ThreadPoolTaskExecutor 这是最常用最通用的一种实现。它包含了java.util.concurrent.ThreadPoolExecutor的属性,并且用TaskExecutor进行包装。
1.2、注解支持调度和异步执行
To enable support for @Scheduled and @Async annotations add @EnableScheduling and @EnableAsync to one of your @Configuration classes:
@Configuration
@EnableAsync
@EnableScheduling
public class AppConfig {
}
特别注意
The default advice mode for processing
@Async
annotations is "proxy" which allows for interception of calls through the proxy only; local calls within the same class cannot get intercepted that way. For a more advanced mode of interception, consider switching to "aspectj" mode in combination with compile-time or load-time weaving.
默认是用代理去处理@Async的,因此,相同类中的方法调用带@Async的方法是无法异步的,这种情况仍然是同步。
举个例子:下面这种,在外部直接调用sayHi()是可以异步执行的,而调用sayHello()时sayHi()仍然是同步执行
public class A { public void sayHello() {
sayHi();
} @Async
public void sayHi() { } }
1.3、@Async注解
在方法上加@Async注解表示这是一个异步调用。换句话说,方法的调用者会立即得到返回,并且实际的方法执行是想Spring的TaskExecutor提交了一个任务。
In other words, the caller will return immediately upon invocation and the actual execution of the method will occur in a task that has been submitted to a Spring TaskExecutor.
@Async
void doSomething() {
// this will be executed asynchronously
}
@Async
void doSomething(String s) {
// this will be executed asynchronously
}
@Async
Future<String> returnSomething(int i) {
// this will be executed asynchronously
}
注意:
@Async methods may not only declare a regular java.util.concurrent.Future return type but also Spring’s org.springframework.util.concurrent.ListenableFuture or, as of Spring 4.2, JDK 8’s java.util.concurrent.CompletableFuture: for richer interaction with the asynchronous task and for immediate composition with further processing steps.
1.4、@Async限定Executor
默认情况下,当在方法上加@Async注解时,将会使用一个支持注解驱动的Executor。然而,@Async注解的value值可以指定一个别的Executor
@Async("otherExecutor")
void doSomething(String s) {
// this will be executed asynchronously by "otherExecutor"
}
这里,otherExecutor是Spring容器中任意Executor bean的名字。
1.5、@Async异常管理
当一个@Async方法有一个Future类型的返回值时,就很容易管理在调Future的get()方法获取任务的执行结果时抛出的异常。如果返回类型是void,那么异常是不会被捕获到的。
public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { @Override
public void handleUncaughtException(Throwable ex, Method method, Object... params) {
// handle exception
}
}
2、线程池配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; @Configuration
@EnableAsync
public class TaskExecutorConfig { private Integer corePoolSize = 30; private Integer maxPoolSize = 50; private Integer keepAliveSeconds = 300; // private Integer queueCapacity = 2000; @Bean("myThreadPoolTaskExecutor")
public ThreadPoolTaskExecutor myThreadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(corePoolSize);
executor.setMaxPoolSize(maxPoolSize);
executor.setKeepAliveSeconds(keepAliveSeconds);
// executor.setQueueCapacity(queueCapacity);
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
} }
调用
@Async("myThreadPoolTaskExecutor")
@Override
public void present(CouponPresentLogEntity entity) {
try {
CouponBaseResponse rst = couponSendRpcService.send(entity.getUserId(), entity.getCouponBatchKey(), "1", entity.getVendorId());
if (null != rst && rst.isSuccess()) {
entity.setStatus(PresentStatusEnum.SUCCESS.getType());
}else {
String reason = (null == rst) ? "响应异常" : rst.getMsg();
entity.setFailureReason(reason);
entity.setStatus(PresentStatusEnum.FAILURE.getType());
}
}catch (Exception ex) {
log.error(ex.getMessage(), ex);
entity.setFailureReason(ex.getMessage());
entity.setStatus(PresentStatusEnum.FAILURE.getType());
}
couponPresentLogDao.update(entity);
}
结果
[INFO ] 2018-05-09 16:27:39.887 [myThreadPoolTaskExecutor-1] [com.ourhours.coupon.rpc.dubbo.ReceiveLogFilter] - receive method-name:send; arguments:[10046031,"4d7cc32f8f7e4b00bca56f6bf4b3b658","1",10001]
[INFO ] 2018-05-09 16:27:39.889 [myThreadPoolTaskExecutor-2] [com.ourhours.coupon.rpc.dubbo.ReceiveLogFilter] - receive method-name:send; arguments:[10046031,"4d7cc32f8f7e4b00bca56f6bf4b3b658","1",10001]
参考:
Spring Framework Reference Documentation 4.3.17.RELEASE
Spring Boot @Async 异步任务执行的更多相关文章
- Spring Boot Async异步执行
异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑. 通常我们使用异步操作都会去创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代码如下: Execut ...
- spring boot @Async异步注解上下文透传
上一篇文章说到,之前使用了@Async注解,子线程无法获取到上下文信息,导致流量无法打到灰度,然后改成 线程池的方式,每次调用异步调用的时候都手动透传 上下文(硬编码)解决了问题. 后面查阅了资料,找 ...
- Spring boot 配置异步处理执行器
示例如下: 1. 新建Maven 项目 async-executor 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...
- spring boot mybatis 打成可执行jar包后启动UnsatisfiedDependencyException异常
我的spring boot + mybatis项目在idea里面执行正常,但发布测试环境打成可执行jar包后就启动失败,提示错误如下: [ ERROR] [2018-08-30 17:23:48] o ...
- Spring Boot Maven 打包可执行Jar文件!
Maven pom.xml 必须包含 <packaging>jar</packaging> <build> <plugins> <plugin&g ...
- 将 Spring boot 项目打成可执行Jar包,及相关注意事项(main-class、缺少 xsd、重复打包依赖)
最近在看 spring boot 的东西,觉得很方便,很好用.对于一个简单的REST服务,都不要自己部署Tomcat了,直接在 IDE 里 run 一个包含 main 函数的主类就可以了. 但是,转念 ...
- Spring Web Async异步处理#Callable #DeferredResult
Spring MVC 对于异步请求处理的两种方式 场景: Tomcat对于主线程性能瓶颈,当Tomcat请求并发数过多时,当线程数满时,就会出现请求等待Tomcat处理,这个时候可以使用子线程处理业务 ...
- Spring boot 项目导出可执行jar
配置文件中添加插件 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>s ...
- spring boot如何处理异步请求异常
springboot自定义错误页面 原创 2017年05月19日 13:26:46 标签: spring-boot 方法一:Spring Boot 将所有的错误默认映射到/error, 实现Err ...
随机推荐
- Androd选取相册照片和拍照处理-android学习之旅(62)
实现如下图所示效果 核心代码 -构建打开相册和拍照的Intent 拍照 File outputImage = new File(Environment.getExternalStorageDirect ...
- Dynamics CRM 2013 subgrid刷新后刷新主表单
项目中会遇到这样的需求,会根据subgrid中的数据变化去更新主表单中的某个或多个字段值,一般的做法就是写插件根据subgrid中实体数据的变化在后台更新主表数据库,但后台更新了要反映到前台就得使用刷 ...
- oracle ebs应用产品安全性-安全性规则
定义: 通过为段指定包括下限值与上限值的值范围,可以定义安全性规则要素.安全性规则要素适用于包括在指定值范围内的所有段值. 可以将每个安全性规则要素标识为"包括"或"排除 ...
- 【leetcode81】Product of Array Except Self
题目描述: 给定一个长度为n的整数数组Array[],输出一个等长的数组result[],这个输出数组,对应位置i是除了Array[i]之外,其他的所有元素的乘积 例如: given [1,2,3,4 ...
- [Ext.Net] 1.x GridPanel列数过多给Menu菜单加滚动条
转自:http://www.ext.net.cn/thread-1944-1-2.html 当GirdPanel列数过多,查看列的显示隐藏时会出现下面下面情况,有部分超出了界面被遮罩住了 要解决这 ...
- mysql进阶(五)数据表中带OR的多条件查询
MySQL数据表中带OR的多条件查询 OR关键字可以联合多个条件进行查询.使用OR关键字时: 条件 1) 只要符合这几个查询条件的其中一个条件,这样的记录就会被查询出来. 2) 如果不符合这些查询条件 ...
- 开源,免费和跨平台 - MVP ComCamp 2015 KEYNOTE
2015年1月31日,作为KEYNOTE演讲嘉宾,我和来自全国各地的开发人员分享了作为一名MVP的一些体会. Keynote – Open Source, Free Tools and Cross P ...
- dos2unix(windows脚本文件放到unix下运行要注意)
在windows下编写的shell脚本文件,直接放到linux下运行,是不行的. infiniDB的倒库脚本文件load.sh,将tbl文件导入infiniDB,怎么运行不成功,不建job.运来,是w ...
- OpenCV 金字塔图像缩放
// image_pyramid.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <string> #incl ...
- 网站开发进阶(十八)js获取html标签中的值
js获取html标签中的值 项目开发过程中,由于需求所迫,需要获取html标签元素中的内容,下面做一简单总结.以下所讲的示例适用于其它标签元素. 主要包括2中方法获取元素内容: 方法一:.innerT ...