Spring Boot @Async 异步任务执行方法

 更新时间:2018年05月10日 10:54:12   作者:不要乱摸  
本篇文章主要介绍了Spring Boot @Async 异步任务执行方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

1、任务执行和调度

Spring用TaskExecutor和TaskScheduler接口提供了异步执行和调度任务的抽象。

Spring的TaskExecutor和java.util.concurrent.Executor接口时一样的,这个接口只有一个方法execute(Runnable task)。

1.1、TaskExecutor类型

Spring已经内置了许多TaskExecutor的实现,你没有必要自己去实现:

  1. SimpleAsyncTaskExecutor  这种实现不会重用任何线程,每次调用都会创建一个新的线程。
  2. SyncTaskExecutor  这种实现不会异步的执行
  3. ConcurrentTaskExecutor  这种实现是java.util.concurrent.Executor的一个adapter。
  4. SimpleThreadPoolTaskExecutor  这种实现实际上是Quartz的SimpleThreadPool的一个子类,它监听Spring的声明周期回调。
  5. 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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Mybatis #foreach中相同的变量名导致值覆盖的问题解决

    Mybatis #foreach中相同的变量名导致值覆盖的问题解决

    本文主要介绍了Mybatis #foreach中相同的变量名导致值覆盖的问题解决,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • 详解在springmvc中解决FastJson循环引用的问题

    详解在springmvc中解决FastJson循环引用的问题

    本篇文章主要介绍了在springmvc中解决FastJson循环引用的问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • Java进阶教程之异常处理

    Java进阶教程之异常处理

    这篇文章主要介绍了Java进阶教程之异常处理,本文讲解了JAVA的异常处理机制、异常的类型、抛出异常、自定义异常等内容,需要的朋友可以参考下
    2014-09-09
  • struts2获取服务器临时目录的方法

    struts2获取服务器临时目录的方法

    这篇文章主要为大家详细介绍了struts2获取服务器临时目录的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-09-09
  • Spring如何正确注入集合类型

    Spring如何正确注入集合类型

    这篇文章主要介绍了Spring如何正确注入集合类型,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09
  • IDEA下SpringBoot指定配置文件启动项目的全过程

    IDEA下SpringBoot指定配置文件启动项目的全过程

    我们在使用springboot项目开发的时候,每次切换环境跑项目的时候,都得修改配置文件的数据库地址,这样来回修改感觉很麻烦,这篇文章主要给大家介绍了关于IDEA下SpringBoot指定配置文件启动项目的相关资料,需要的朋友可以参考下
    2023-06-06
  • SpringCloud Gateway的熔断限流配置实现方法

    SpringCloud Gateway的熔断限流配置实现方法

    Spring Cloud Gateway支持通过配置熔断和限流机制来保证服务的稳定性和可用性,可通过Hystrix和Resilience4j两种方式实现。Hystrix通过注解和配置文件实现熔断限流,Resilience4j通过编程式配置实现
    2023-04-04
  • java 全角半角字符转换的方法实例

    java 全角半角字符转换的方法实例

    这篇文章主要介绍了java 全角半角字符转换的方法,大家参考使用吧
    2013-11-11
  • Spring Boot启动端口修改方法

    Spring Boot启动端口修改方法

    spring boot是个好东西,可以不用容器直接在main方法中启动,而且无需配置文件,方便快速搭建环境。下面通过本文给大家分享Spring Boot修改启动端口的方法,感兴趣的的朋友一起看看吧
    2017-07-07
  • Java日期时间调整的几种方式汇总

    Java日期时间调整的几种方式汇总

    Calendar类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可,这篇文章主要介绍了Java日期时间调整的几种方式,需要的朋友可以参考下
    2023-05-05

最新评论