spring@Async注解实现异步方法调用

时间:2022-05-25 23:18:09

# 概述
> 如何实现异步方法调用,很多人首先会想到使用线程或者线程池技术,springboot中有一个很简单的方法可以实现异步方法调用,那就是在方法上使用@Async注解

# 例子
> 首先在Springboot启动类上添加@EnableAsync注解,表明使用@Async注解
``` java
@SpringBootApplication
@EnableAsync
public class Application{

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
```

> 异步调用测试类

``` java
package com.example.mongo_demo.test;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
* created by qinming on 2018/5/17
**/
@Component
public class AsyncTest {
public static final Logger LOGGER = LoggerFactory.getLogger(AsyncTest.class);

@Async
public void asyn1() throws InterruptedException {
Long timeMilles = System.currentTimeMillis();
Thread.sleep(7000);
LOGGER.error("》》》》》》》》》》》》asyn1耗时:{}《《《《《《《《《",System.currentTimeMillis()-timeMilles);
}
@Async
public void asyn2() throws InterruptedException {
Long timeMilles = System.currentTimeMillis();
Thread.sleep(7000);
LOGGER.error("》》》》》》》》》》》》asyn2耗时:{}《《《《《《《《《",System.currentTimeMillis()-timeMilles);
}
@Async
public void asyn3() throws InterruptedException {
Long timeMilles = System.currentTimeMillis();
Thread.sleep(10000);
LOGGER.error("》》》》》》》》》》》》asyn3耗时:{}《《《《《《《《《",System.currentTimeMillis()-timeMilles);
}
}
```

> 通过一个简单的接口测试即可
``` java
/**
* created by qinming on 2018/5/17
**/
@RestController
@RequestMapping("/api")
public class DemostrationController {
@Autowired
private AsyncTest asyncTest;
public static final Logger LOGGER = LoggerFactory.getLogger(DemostrationController.class);
@RequestMapping("/async/test")
public String get() throws InterruptedException {
long timeMillis = System.currentTimeMillis();
asyncTest.asyn1();
asyncTest.asyn2();
asyncTest.asyn3();
Thread.sleep(1000);
LOGGER.error("//////耗时:{}",System.currentTimeMillis()-timeMillis);
return "";
}
}

```
> 结果如下:
```
2018-05-17 14:27:40.252 ERROR 7843 --- [nio-8080-exec-1] c.e.m.ctrl.DemostrationController : //////耗时:1019
2018-05-17 14:27:46.253 ERROR 7843 --- [cTaskExecutor-1] com.example.mongo_demo.test.AsyncTest : 》》》》》》》》》》》》asyn1耗时:7003《《《《《《《《《
2018-05-17 14:27:46.255 ERROR 7843 --- [cTaskExecutor-2] com.example.mongo_demo.test.AsyncTest : 》》》》》》》》》》》》asyn2耗时:7005《《《《《《《《《
2018-05-17 14:27:49.254 ERROR 7843 --- [cTaskExecutor-3] com.example.mongo_demo.test.AsyncTest : 》》》》》》》》》》》》asyn3耗时:10004《《《《《《《《《

```
> 这样就实现了异步方法的简单调用

# 带有返回值的方法如何使用@Async注解
> 使用@Async注解的方法返回值为java.util.concurrent.Future 的实现类 org.springframework.scheduling.annotation.AsyncResult 类型,代码如下:

``` Java
/**
* created by qinming on 2018/5/17
**/
@Component
public class AsyncWIthReturnValueTest {
public static final Logger LOGGER = LoggerFactory.getLogger(AsyncWIthReturnValueTest.class);

@Async
public Future<String> aysnc1() throws InterruptedException {
Long st = System.currentTimeMillis();
LOGGER.error(">>>>>>>aysnc1 start at {}>>>>>",st);
Thread.sleep(7000);
long end =System.currentTimeMillis();
LOGGER.error(">>>>>>>aysnc1 cost :{}>>>>>",end - st);
return new AsyncResult<String>("aysnc1 is done");
}
@Async
public Future<String> aysnc2() throws InterruptedException {
Long st = System.currentTimeMillis();
LOGGER.error(">>>>>>>aysnc2 start at {}>>>>>",st);
Thread.sleep(7000);
long end =System.currentTimeMillis();
LOGGER.error(">>>>>>>aysnc2 cost :{}>>>>>",end - st);
return new AsyncResult<String>("aysnc2 is done");
}
@Async
public Future<String> aysnc3() throws InterruptedException {
Long st = System.currentTimeMillis();
LOGGER.error(">>>>>>>aysnc3 start at {}>>>>>",st);
Thread.sleep(7000);
long end =System.currentTimeMillis();
LOGGER.error(">>>>>>>aysnc3 cost :{}>>>>>",end - st);
return new AsyncResult<String>("aysnc3 is done");
}
}
```

> 调用方法例子如下:
``` Java
@RequestMapping("/async/test")
public String get() throws InterruptedException, ExecutionException {
long timeMillis = System.currentTimeMillis();
Future<String> async1 = asyncWIthReturnValueTest.aysnc1();
Future<String> async2 = asyncWIthReturnValueTest.aysnc2();
Future<String> async3 = asyncWIthReturnValueTest.aysnc3();
while (true) {
if (async1.isDone()){
LOGGER.error("----{}1-------",async1.get());
}
if (async2.isDone()){
LOGGER.error("----{}2-------",async2.get());
}
if (async3.isDone()){
LOGGER.error("----{}3-------",async3.get());
}
if (async1.isDone() && async2.isDone() && async3.isDone()) {
break;
}
Thread.sleep(1000);
}
LOGGER.error("//////耗时:{}",System.currentTimeMillis()-timeMillis);
return "SUCCESS";
}
```