异步调用-无返回值
在启动类上需要添加上@EnableAsync注解开启异步支持
@EnableAsync
@SpringBootApplication
public class SpringbootStudyApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootStudyApplication.class, args);
}
}
@Slf4j
@RestController
public class TestController {
@Resource
private TestService testService;
@RequestMapping(value = "/test/async", method = RequestMethod.GET)
public Object test(){
log.info("调用开始,{}", Thread.currentThread().getName());
Map<String, Object> resultMap = Maps.newHashMap();
testService.testAsync();
resultMap.put("msg", "调用成功");
log.info("调用结束,{}", Thread.currentThread().getName());
return resultMap;
}
}
需要异步执行的方法只需要在方法上添加@Async注解即可
@Slf4j
@Service
public class TestService {
@Async
public void testAsync(){
try {
log.info("sleep开始,{}", Thread.currentThread().getName());
TimeUnit.SECONDS.sleep(3);
log.info("sleep结束,{}", Thread.currentThread().getName());
} catch (Exception e){
log.error("Exception", e);
}
}
}
访问http://localhost:8080/test/async,以上示例执行的日志输出如下
2019-07-16 08:35:04.875 INFO 6216 --- [nio-8080-exec-1] c.u.s.controller.TestController : 调用开始,http-nio-8080-exec-1
2019-07-16 08:35:04.889 INFO 6216 --- [nio-8080-exec-1] c.u.s.controller.TestController : 调用结束,http-nio-8080-exec-1
2019-07-16 08:35:04.900 INFO 6216 --- [ task-1] c.u.springbootstudy.service.TestService : sleep开始,task-1
2019-07-16 08:35:07.900 INFO 6216 --- [ task-1] c.u.springbootstudy.service.TestService : sleep结束,task-1
异步调用-有返回值
上面测试了无返回值的异步调用,下面测试有返回值的异步调用
@RequestMapping(value = "/test/asyncReturn", method = RequestMethod.GET)
public Object testAsyncReturn() throws Exception{
log.info("调用开始,{}", Thread.currentThread().getName());
Map<String, Object> resultMap = Maps.newHashMap();
List<Future<String>> futureList = Lists.newArrayList();
for (int i = 0; i < 10; i ++) {
Future<String> future = testService.testAsync("Tom" + i);
futureList.add(future);
}
resultMap.put("msg", "调用成功");
log.info("调用结束,{}", Thread.currentThread().getName());
List<String> resultList = Lists.newArrayList();
for (Future future : futureList) {
String string = (String) future.get();
resultList.add(string);
}
log.info("主线程获取结果:{}", resultList);
return resultMap;
}
@Async
public Future<String> testAsync(String name){
try {
log.info("sleep开始,threadName={}, name={}", Thread.currentThread().getName(), name);
TimeUnit.SECONDS.sleep(3);
log.info("sleep结束,threadName={}, name={}", Thread.currentThread().getName(), name);
} catch (Exception e){
log.error("Exception", e);
}
return new AsyncResult<>("Hello " + name);
}
访问 http://localhost:8080/test/asyncReturn 时的日志输出如下
2019-07-16 08:47:20.518 INFO 7572 --- [nio-8080-exec-2] c.u.s.controller.TestController : 调用开始,http-nio-8080-exec-2
2019-07-16 08:47:20.531 INFO 7572 --- [nio-8080-exec-2] c.u.s.controller.TestController : 调用结束,http-nio-8080-exec-2
2019-07-16 08:47:20.540 INFO 7572 --- [ task-1] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-1, name=Tom0
2019-07-16 08:47:20.540 INFO 7572 --- [ task-7] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-7, name=Tom6
2019-07-16 08:47:20.540 INFO 7572 --- [ task-6] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-6, name=Tom5
2019-07-16 08:47:20.540 INFO 7572 --- [ task-8] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-8, name=Tom7
2019-07-16 08:47:20.540 INFO 7572 --- [ task-5] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-5, name=Tom4
2019-07-16 08:47:20.540 INFO 7572 --- [ task-4] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-4, name=Tom3
2019-07-16 08:47:20.540 INFO 7572 --- [ task-3] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-3, name=Tom2
2019-07-16 08:47:20.541 INFO 7572 --- [ task-2] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-2, name=Tom1
2019-07-16 08:47:23.540 INFO 7572 --- [ task-1] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-1, name=Tom0
2019-07-16 08:47:23.540 INFO 7572 --- [ task-7] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-7, name=Tom6
2019-07-16 08:47:23.542 INFO 7572 --- [ task-6] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-6, name=Tom5
2019-07-16 08:47:23.544 INFO 7572 --- [ task-2] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-2, name=Tom1
2019-07-16 08:47:23.546 INFO 7572 --- [ task-7] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-7, name=Tom8
2019-07-16 08:47:23.545 INFO 7572 --- [ task-3] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-3, name=Tom2
2019-07-16 08:47:23.547 INFO 7572 --- [ task-3] c.u.springbootstudy.service.TestService : sleep开始,threadName=task-3, name=Tom9
2019-07-16 08:47:23.549 INFO 7572 --- [ task-4] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-4, name=Tom3
2019-07-16 08:47:23.551 INFO 7572 --- [ task-5] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-5, name=Tom4
2019-07-16 08:47:23.553 INFO 7572 --- [ task-8] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-8, name=Tom7
2019-07-16 08:47:26.548 INFO 7572 --- [ task-3] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-3, name=Tom9
2019-07-16 08:47:26.548 INFO 7572 --- [ task-7] c.u.springbootstudy.service.TestService : sleep结束,threadName=task-7, name=Tom8
2019-07-16 08:47:26.549 INFO 7572 --- [nio-8080-exec-2] c.u.s.controller.TestController : 主线程获取结果:[Hello Tom0, Hello Tom1, Hello Tom2, Hello Tom3, Hello Tom4, Hello Tom5, Hello Tom6, Hello Tom7, Hello Tom8, Hello Tom9]
在08:47:20的时候有8个线程几乎同时开始了sleep,在08:47:23时这8个线程sleep结束。其中两个线程继续开始执行sleep,08:47:26时这两个线程结束sleep。
主线程在08:47:26时拿到所有的结果。