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整合quartz实现多个定时任务的方法
-
spring boot使用自定义配置的线程池执行Async异步任务
-
spring定时任务执行两次及tomcat部署缓慢问题的解决方法
-
Spring里的Async注解实现异步操作的方法步骤
-
深入理解spring boot异步调用方式@Async
-
Spring Boot利用@Async异步调用:使用Future及定义超时详解
-
spring boot aop 记录方法执行时间代码示例
-
Spring Boot利用@Async如何实现异步调用:自定义线程池
-
Spring Boot利用@Async异步调用:ThreadPoolTaskScheduler线程池的优雅关闭详解