这篇文章主要讲解了“springboot使用异步注解@Async获取执行结果”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“springboot使用异步注解@Async获取执行结果”吧!
一、引言
二、获取异步执行结果
1、环境介绍
2、错误的方式
3、正确方式
三、异步执行@Async注解
四、总结
在java后端开发中经常会碰到处理多个任务的情况,比如一个方法中要调用多个请求,然后把多个请求的结果合并后统一返回,一般情况下调用其他的请求一般都是同步的,也就是每个请求都是阻塞的,那么这个处理时间必定是很长的,有没有一种方法可以让多个请求异步处理那,答案是有的。
springboot中提供了很便利的方式可以解决上面的问题,那就是异步注解@Async。正确的使用该注解可以使你的程序飞起,相反如果使用不当那么并不会取到理想的效果。
下面是我的controller,SyncController.java
package com.atssg.controller; import com.atssg.service.MySyncService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @Slf4j @RestController @RequestMapping("/sync") public class SyncController { @Autowired private MySyncService syncService; @GetMapping(value = "/test") public String test() { String str=null; try { log.info("start"); str = syncService.asyncMethod(); log.info("str:{}", str); return str; } catch (Exception e) { e.printStackTrace(); } return str; } }
在controller中就是调用下层的方法并返回,再看service层的类MySyncService.java
package com.atssg.service; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; @Service public class MySyncService { @Autowired private SyncService syncService; /** * 异步方法 * * @return * @throws InterruptedException * @throws ExecutionException */ public String asyncMethod() throws InterruptedException, ExecutionException { Future<String> result1 = syncService.method1("I"); Future<String> result2 = syncService.method2("love"); Future<String> result3 = syncService.method3("async"); String str = result1.get(); String str2 = result2.get(); String str3 = result3.get(); String result = str + str2 + str3; return result; } /** * 同步方法 * * @return * @throws InterruptedException * @throws ExecutionException */ public String syncMethod() throws InterruptedException, ExecutionException { /*同步写法*/ String str = syncService.method1("I").get(); String str2 = syncService.method2("love").get(); String str3 = syncService.method3("async").get(); return str + str2 + str3; } }
上面便是service类,仅仅是调用下次异步层的方法,并取得返回值。上面类中有两个方法,其写法也类似但结果却大不相同,后面详说。
下面是异步层的方法,SyncService.java
package com.atssg.service; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.AsyncResult; import org.springframework.stereotype.Service; import java.util.concurrent.Future; @Service @Async public class SyncService { //@Async public Future<String> method1(String str) throws InterruptedException { Thread.sleep(1000*10); return new AsyncResult<>( str); } //@Async public Future<String> method2(String str) throws InterruptedException { Thread.sleep(1000*5); return new AsyncResult<>(str); } // @Async public Future<String> method3(String str) throws InterruptedException { Thread.sleep(1000*15); return new AsyncResult<>(str); } }
该类使用@Async注解,表明该类中所有的方法都是异步执行的,其中@Async可修饰类也可以修饰方法。
这便是所有的环境。
在MySyncService中有两个方法,先看其中一个方法
public String syncMethod() throws InterruptedException, ExecutionException { /*同步写法*/ String str = syncService.method1("I").get(); String str2 = syncService.method2("love").get(); String str3 = syncService.method3("async").get(); return str + str2 + str3; }
这种写法是调用异步方法后立即调用get()方法,即获取结果,下面看测试结果,在controllor中调用该方法,下面看执行结果
2021-08-21 11:06:28.612 INFO 3584 --- [nio-8080-exec-1] com.atssg.controller.SyncController : start
2021-08-21 11:06:58.651 INFO 3584 --- [nio-8080-exec-1] com.atssg.controller.SyncController : str:Iloveasync
可以看到共执行了30s,在异步层的方法中的三个方法如下,
//@Async public Future<String> method1(String str) throws InterruptedException { Thread.sleep(1000*10); return new AsyncResult<>( str); } //@Async public Future<String> method2(String str) throws InterruptedException { Thread.sleep(1000*5); return new AsyncResult<>(str); } // @Async public Future<String> method3(String str) throws InterruptedException { Thread.sleep(1000*15); return new AsyncResult<>(str); }
可以看到这三个方法分别是睡眠10s、5s、15s,这就很好理解了syncMethod()方法中的写法是同步的,未达到异步的目的,切记调用完异步方法进接着调用get()方法不是异步的方式,而是同步的。
上面看了错误的用法,下面看正确的方式,
public String asyncMethod() throws InterruptedException, ExecutionException { Future<String> result1 = syncService.method1("I"); Future<String> result2 = syncService.method2("love"); Future<String> result3 = syncService.method3("async"); String str = result1.get(); String str2 = result2.get(); String str3 = result3.get(); String result = str + str2 + str3; return result; }
这种方式是首先调用异步方法,然后分别调用get()方法,取得执行结果。下面看测试结果
2021-08-21 11:17:23.516 INFO 3248 --- [nio-8080-exec-1] com.atssg.controller.SyncController : start
2021-08-21 11:17:38.535 INFO 3248 --- [nio-8080-exec-1] com.atssg.controller.SyncController : str:Iloveasync
执行时间未15s,这就很好解释了,异步层的三个方法,分别睡眠的时间是10s、5s、15s,既然是异步执行的,那么总的执行时间肯定是三个方法中最长的那个,符合测试结果。这才@Async正确的打开姿势。
@Async注解的定义如下,
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Async { String value() default ""; }
可以看到该注解可以用在类及方法上,用在类上表示类中的所有方法都是异步的,用在方法上表示该方法是异步的。
今天的文章分享到这里,主要分享了关于@Async注解在获取执行结果的时候的坑,一定要先调用异步方法,然后再调用get()方法,获取结果,其中get方法还有一个重载的,可以设置超时时间,即超过设置的超时时间便返回,不再等待,各位小伙伴可以自己试验。
V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
下次继续分享有关@Async注解使用的一些小细节,欢迎持续关注。
感谢各位的阅读,以上就是“springboot使用异步注解@Async获取执行结果”的内容了,经过本文的学习后,相信大家对springboot使用异步注解@Async获取执行结果这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。