springboot:使用异步注解@Async获取执行结果的坑

springboot使用异步注解@Async的那些坑

一、引言

在java后端开发中经常会碰到处理多个任务的情况,比如一个方法中要调用多个请求,然后把多个请求的结果合并后统一返回,一般情况下调用其他的请求一般都是同步的,也就是每个请求都是阻塞的,那么这个处理时间必定是很长的,有没有一种方法可以让多个请求异步处理那,答案是有的。

springboot中提供了很便利的方式可以解决上面的问题,那就是异步注解@Async。正确的使用该注解可以使你的程序飞起,相反如果使用不当那么并不会取到理想的效果。

二、获取异步执行结果 1、环境介绍

下面是我的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可修饰类也可以修饰方法。

这便是所有的环境。

2、错误的方式

在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); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwwssj.html