Spring Boot通过@Async注解实现异步调用

@Aysnc其实是Spring内的一个组件,可以完成对类内单个或者多个方法实现异步调用,这样可以大大的节省等待耗时。内部实现机制是线程池任务ThreadPoolTaskExecutor,通过线程池来对配置@Async的方法或者类做出执行动作。

线程任务池配置

我们创建一个ListenerAsyncConfiguration,并且使用@EnableAsync注解开启支持异步处理,具体代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Configuration
@EnableAsync
public class ListenerAsyncConfiguration implements AsyncConfigurer {
/**
* 获取异步线程池执行对象
* @return
*/
@Override
public Executor getAsyncExecutor() {
//使用Spring内置线程池任务对象
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//设置线程池参数
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.setQueueCapacity(25);
taskExecutor.initialize();
return taskExecutor;
}

@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
}
}

异步调用测试

任务类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Slf4j
@Component
public class AsyncTask {
@Async
public void doTask1() {
try {
long start = System.currentTimeMillis();
Thread.sleep(3000);
long end = System.currentTimeMillis();
log.info("任务1结束, 耗时: " + (end-start));
} catch (Exception e) {
e.printStackTrace();
}
}

@Async
public void doTask2() {
try {
long start = System.currentTimeMillis();
Thread.sleep(3000);
long end = System.currentTimeMillis();
log.info("任务2结束, 耗时: " + (end-start));
} catch (Exception e) {
e.printStackTrace();
}
}

@Async
public void doTask3() {
try {
long start = System.currentTimeMillis();
Thread.sleep(5000);
long end = System.currentTimeMillis();
log.info("任务3结束, 耗时: " + (end-start));
} catch (Exception e) {
e.printStackTrace();
}
}
}

控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Slf4j
@RestController
public class AsyncController {
@Autowired
private AsyncTask asyncTask;

@RequestMapping("/async")
public String async() {
long start = System.currentTimeMillis();
asyncTask.doTask1();
asyncTask.doTask2();
asyncTask.doTask3();
long end = System.currentTimeMillis();
log.info("请求耗时: " + (end-start));
return "SUCCESS";
}
}

输出结果

1
2
3
4
请求耗时: 4
任务2结束, 耗时: 3001
任务1结束, 耗时: 3001
任务3结束, 耗时: 5001

带有返回值的方法如何使用@Async注解

使用@Async注解的方法返回值为java.util.concurrent.Future的实现类org.springframework.scheduling.annotation.AsyncResult类型

任务类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@Slf4j
@Component
public class AsyncTaskWithResult {
@Async
public Future<String> doTask1() {
try {
long start = System.currentTimeMillis();
Thread.sleep(3000);//静静的沉睡3秒钟
long end = System.currentTimeMillis();
log.info("任务1结束, 耗时: " + (end-start));
return new AsyncResult<String>("Aysnc task 1 is done");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

@Async
public Future<String> doTask2() {
try {
long start = System.currentTimeMillis();
Thread.sleep(3000);//静静的沉睡3秒钟
long end = System.currentTimeMillis();
log.info("任务2结束, 耗时: " + (end-start));
return new AsyncResult<String>("Aysnc task 2 is done");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

@Async
public Future<String> doTask3() {
try {
long start = System.currentTimeMillis();
Thread.sleep(5000);//静静的沉睡5秒钟
long end = System.currentTimeMillis();
log.info("任务3结束, 耗时: " + (end-start));
return new AsyncResult<String>("Aysnc task 3 is done");
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

控制器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Slf4j
@RestController
public class AsyncController {
@Autowired
private AsyncTaskWithResult asyncTaskWithResult;

@RequestMapping("/async_return")
public String asyncReturn() {
long start = System.currentTimeMillis();
Future<String> async1 = asyncTaskWithResult.doTask1();
Future<String> async2 = asyncTaskWithResult.doTask2();
Future<String> async3 = asyncTaskWithResult.doTask3();
try {
while (true) {
if (async1 != null && async1.isDone()) {
log.info("任务1返回: " + async1.get());
}
if (async2 != null && async2.isDone()) {
log.info("任务2返回: " + async2.get());
}
if (async3 != null && async3.isDone()) {
log.info("任务3返回: " + async3.get());
}
if ((async1 == null || async1.isDone()) &&
(async2 == null || async2.isDone()) &&
(async3 == null || async3.isDone())) {
break;
}
Thread.sleep(1000);
}
} catch (Exception e) {

}
long end = System.currentTimeMillis();
log.info("请求耗时: " + (end-start));
return "SUCCESS";
}
}

输出结果

1
2
3
4
5
6
7
8
9
任务2结束, 耗时: 3000
任务1结束, 耗时: 3000
任务1返回: Aysnc task 1 is done
任务2返回: Aysnc task 2 is done
任务3结束, 耗时: 5001
任务1返回: Aysnc task 1 is done
任务2返回: Aysnc task 2 is done
任务3返回: Aysnc task 3 is done
请求耗时: 5017

Powered by AppBlog.CN     浙ICP备14037229号

Copyright © 2012 - 2020 APP开发技术博客 All Rights Reserved.

访客数 : | 访问量 :