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:

  1. @Configuration
  2. @EnableAsync
  3. @EnableScheduling
  4. public class AppConfig {
  5. }

特别注意

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()仍然是同步执行

  1. public class A {
  2.  
  3. public void sayHello() {
  4. sayHi();
  5. }
  6.  
  7. @Async
  8. public void sayHi() {
  9.  
  10. }
  11.  
  12. }

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.

  1. @Async
  2. void doSomething() {
  3. // this will be executed asynchronously
  4. }
  1. @Async
  2. void doSomething(String s) {
  3. // this will be executed asynchronously
  4. }
  1. @Async
  2. Future<String> returnSomething(int i) {
  3. // this will be executed asynchronously
  4. }

注意:

@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

  1. @Async("otherExecutor")
  2. void doSomething(String s) {
  3. // this will be executed asynchronously by "otherExecutor"
  4. }

这里,otherExecutor是Spring容器中任意Executor bean的名字。

1.5、@Async异常管理

当一个@Async方法有一个Future类型的返回值时,就很容易管理在调Future的get()方法获取任务的执行结果时抛出的异常。如果返回类型是void,那么异常是不会被捕获到的。

  1. public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
  2.  
  3. @Override
  4. public void handleUncaughtException(Throwable ex, Method method, Object... params) {
  5. // handle exception
  6. }
  7. }

2、线程池配置

  1. import org.springframework.context.annotation.Bean;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.scheduling.annotation.EnableAsync;
  4. import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
  5.  
  6. @Configuration
  7. @EnableAsync
  8. public class TaskExecutorConfig {
  9.  
  10. private Integer corePoolSize = 30;
  11.  
  12. private Integer maxPoolSize = 50;
  13.  
  14. private Integer keepAliveSeconds = 300;
  15.  
  16. // private Integer queueCapacity = 2000;
  17.  
  18. @Bean("myThreadPoolTaskExecutor")
  19. public ThreadPoolTaskExecutor myThreadPoolTaskExecutor() {
  20. ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
  21. executor.setCorePoolSize(corePoolSize);
  22. executor.setMaxPoolSize(maxPoolSize);
  23. executor.setKeepAliveSeconds(keepAliveSeconds);
  24. // executor.setQueueCapacity(queueCapacity);
  25. executor.setWaitForTasksToCompleteOnShutdown(true);
  26. executor.initialize();
  27. return executor;
  28. }
  29.  
  30. }

调用

  1. @Async("myThreadPoolTaskExecutor")
  2. @Override
  3. public void present(CouponPresentLogEntity entity) {
  4. try {
  5. CouponBaseResponse rst = couponSendRpcService.send(entity.getUserId(), entity.getCouponBatchKey(), "1", entity.getVendorId());
  6. if (null != rst && rst.isSuccess()) {
  7. entity.setStatus(PresentStatusEnum.SUCCESS.getType());
  8. }else {
  9. String reason = (null == rst) ? "响应异常" : rst.getMsg();
  10. entity.setFailureReason(reason);
  11. entity.setStatus(PresentStatusEnum.FAILURE.getType());
  12. }
  13. }catch (Exception ex) {
  14. log.error(ex.getMessage(), ex);
  15. entity.setFailureReason(ex.getMessage());
  16. entity.setStatus(PresentStatusEnum.FAILURE.getType());
  17. }
  18. couponPresentLogDao.update(entity);
  19. }

结果

  1. [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]
  2. [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 异步任务执行的更多相关文章

  1. Spring Boot Async异步执行

    异步调用就是不用等待结果的返回就执行后面的逻辑,同步调用则需要等带结果再执行后面的逻辑. 通常我们使用异步操作都会去创建一个线程执行一段逻辑,然后把这个线程丢到线程池中去执行,代码如下: Execut ...

  2. spring boot @Async异步注解上下文透传

    上一篇文章说到,之前使用了@Async注解,子线程无法获取到上下文信息,导致流量无法打到灰度,然后改成 线程池的方式,每次调用异步调用的时候都手动透传 上下文(硬编码)解决了问题. 后面查阅了资料,找 ...

  3. Spring boot 配置异步处理执行器

    示例如下: 1. 新建Maven 项目 async-executor 2.pom.xml <project xmlns="http://maven.apache.org/POM/4.0 ...

  4. spring boot mybatis 打成可执行jar包后启动UnsatisfiedDependencyException异常

    我的spring boot + mybatis项目在idea里面执行正常,但发布测试环境打成可执行jar包后就启动失败,提示错误如下: [ ERROR] [2018-08-30 17:23:48] o ...

  5. Spring Boot Maven 打包可执行Jar文件!

    Maven pom.xml 必须包含 <packaging>jar</packaging> <build> <plugins> <plugin&g ...

  6. 将 Spring boot 项目打成可执行Jar包,及相关注意事项(main-class、缺少 xsd、重复打包依赖)

    最近在看 spring boot 的东西,觉得很方便,很好用.对于一个简单的REST服务,都不要自己部署Tomcat了,直接在 IDE 里 run 一个包含 main 函数的主类就可以了. 但是,转念 ...

  7. Spring Web Async异步处理#Callable #DeferredResult

    Spring MVC 对于异步请求处理的两种方式 场景: Tomcat对于主线程性能瓶颈,当Tomcat请求并发数过多时,当线程数满时,就会出现请求等待Tomcat处理,这个时候可以使用子线程处理业务 ...

  8. Spring boot 项目导出可执行jar

    配置文件中添加插件 <plugin> <groupId>org.springframework.boot</groupId> <artifactId>s ...

  9. spring boot如何处理异步请求异常

    springboot自定义错误页面 原创 2017年05月19日 13:26:46 标签: spring-boot   方法一:Spring Boot 将所有的错误默认映射到/error, 实现Err ...

随机推荐

  1. Bias and Variance 偏置和方差

    偏置和方差 参考资料:http://scott.fortmann-roe.com/docs/BiasVariance.html http://www.cnblogs.com/kemaswill/ Bi ...

  2. Scipy教程 - 统计函数库scipy.stats

    http://blog.csdn.net/pipisorry/article/details/49515215 统计函数Statistical functions(scipy.stats) Pytho ...

  3. CUDA学习,环境配置和简单例子

    根据摩尔定律,每18个月,硬件的速度翻一番.纵使CPU的主频会越来越高,但是其核数受到了极大的限制,目前来说,最多只有8个或者9个核.相比之下,GPU具有很大的优势,他有成千上万个核,能完成大规模的并 ...

  4. Tomcat的管道

    Tomcat中按照包含关系一共有四个容器--StandardEngine.StandardHost.StandardContext和StandardWrapper,对这四个容器的详细解析后面会涉及,请 ...

  5. 设计模式之——工厂模式(B)

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/41142929 工厂方法模式定义了一个创建对象的接口,但由子 ...

  6. [java]负数的二进制编码——越是基础的越是要掌握

     ),第二位代表有几个10(即几个101),第三位代表有几个100(即有几个102)-,用小学课本上的说法就是:个位上的数表示几个1,十位上的数表示向个10,百位上的数表示几个100-- 同理可证 ...

  7. 【Android】自定义ListView的Adapter报空指针异常解决方法

    刚刚使用ViewHolder的方法拉取ListView的数据,但是总会报异常.仔细查看代码,都正确. 后来打开adapter类,发现getView的返回值为null. 即return null. 将n ...

  8. 你可能不知道的5种 CSS 和 JS 的交互方式

    翻译人员: 铁锚 翻译日期: 2014年01月22日 原文日期: 2014年01月20日 原文链接:  5 Ways that CSS and JavaScript Interact That You ...

  9. Python学习笔记 - 高阶函数

    高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数abs()为例,调用该函数用以下 ...

  10. 关于iOS中几种第三方对XML/JSON数据解析的使用

    Json XML 大数据时代,我们需要从网络中获取海量的新鲜的各种信息,就不免要跟着两个家伙打交道,这是两种结构化的数据交换格式.一般来讲,我们会从网络获取XML或者Json格式的数据,这些数据有着特 ...