编程知识 cdmana.com

The @ async asynchronous call of spring boot series

Let me write it out front

hello , Long time no see , How are you ?

What I have brought to you today is a problem I encountered in the actual project .

The process is roughly , Call interface , Then update the data returned by the interface to the local database , And then it goes back to the front end . Updating to the local database was originally done asynchronously .

Back home on National Day , The company called , Turn the front end for a few seconds , Then there is no data . After the check , yes Redis Something went wrong. , Can not use .

What do you mean ?

Data requested from the interface , Update to local database , Here's a strategy , Put the data into Redis in , Then compare , If it's not consistent , Update again .Redis Unavailable , Then all query the database , It's going to be slow , The front-end request interface is usually 5s Overtime .

If it's asynchronous , That would not have happened .

therefore , Let's take a look at the time , My code is clearly asynchronous , Why didn't it work ?

@Async Invalid

Let's look at an example .

Controller The code is as follows :

@GetMapping("/invalid")
public String invalidAsyncExample() {
iTestAsyncService.invalidAsyncExample();
return " Testing is completed " + LocalDateTime.now().toString();
}

Service The code is as follows :

@Override
public void invalidAsyncExample() {
log.info(" technological process -1-{}", Thread.currentThread().getId());
invalidAsyncTask();
log.info(" technological process -3-{}", Thread.currentThread().getId());
}

Async The code is as follows :

@Async
public void invalidAsyncTask() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(" technological process -2-{}", Thread.currentThread().getId());
}

Execution results :

2020-11-11 21:14:06.784 INFO 13592 --- [nio-8080-exec-1] c.f.s.a.s.impl.TestAsyncServiceImpl     : technological process -1-125
2020-11-11 21:14:08.785 INFO 13592 --- [nio-8080-exec-1] c.f.s.a.s.impl.TestAsyncServiceImpl     : technological process -2-125
2020-11-11 21:14:08.785 INFO 13592 --- [nio-8080-exec-1] c.f.s.a.s.impl.TestAsyncServiceImpl     : technological process -3-125

Result analysis : It's really synchronous , There's nothing to add @Async Of , Asynchronous doesn't work ?

With this question , Search for answers on Baidu . meanwhile , Also decided to read this piece of source code . Would like to have a look , How does this asynchrony work .

By reading the source code , Will find ,Spring The default is to use a proxy to implement asynchronous .

What do you mean ?

You can think of it this way , The class you call needs Spring Acting for you , Then it can be executed asynchronously .

Example code above ,invalidAsyncTask(); The method called is very clear , There is no need for an agent , Now Spring You can't do it asynchronously .

About source code analysis , Later, when I wrote the source blog , Come again .

Asynchronous tasks with no return value

First of all , need @EnableAsync

Controller:

@GetMapping("/no-value")
public String noValueAsyncExample() {
iTestAsyncService.noValueAsyncExample();
return " Testing is completed " + LocalDateTime.now().toString();
}

Service:

@Override
public void noValueAsyncExample() {
log.info(" technological process -1-{}", Thread.currentThread().getId());
iAsyncService.exampleTask();
log.info(" technological process -3-{}", Thread.currentThread().getId());
}

Time consuming tasks :

@Override
public void exampleTask() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(" Time consuming tasks -2-{}", Thread.currentThread().getId());
}

Async:

@Override
@Async
public void exampleTask() {
iTestAsyncService.exampleTask();
}

Pay attention here , Because we put time-consuming tasks in the same service Inside , So there's the problem of circular dependency , Need to use @Lazy .

test result :

2020-11-11 22:32:50.019 INFO 18888 --- [nio-8080-exec-7] c.f.s.a.s.impl.TestAsyncServiceImpl     : technological process -1-131
2020-11-11 22:32:50.020 INFO 18888 --- [nio-8080-exec-7] c.f.s.a.s.impl.TestAsyncServiceImpl     : technological process -3-131
2020-11-11 22:32:52.021 INFO 18888 --- [         task-9] c.f.s.a.s.impl.TestAsyncServiceImpl     : Time consuming tasks -2-152

Asynchronous tasks with return values

It's also necessary @EnableAsync

Controller:

@GetMapping("/value")
public int valueAsyncExample() {
return iTestAsyncService.valueAsyncExample();
}

Service:

@Override
public int valueAsyncExample() {
int result = 0;

long startTime = System.currentTimeMillis();

List<Future<Integer>> futureList = new ArrayList<>();

for (int i = 0; i < 10; i++) {
Future<Integer> future = iAsyncService.addTask(i);
futureList.add(future);
}

for (Future<Integer> f : futureList) {
Integer value = null;
try {
value = f.get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
if (value != null)
result += value;
}

long endTime = System.currentTimeMillis();

log.info(" Time consuming {} s", (endTime - startTime) / 1000D);

return result;
}

Mission :

@Override
public Future<Integer> addTask(int n) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.info(" Calculation task -{}", Thread.currentThread().getId());
return AsyncResult.forValue(n + 2);
}

Async:

@Override
@Async
public Future<Integer> addTask(int i) {
return iTestAsyncService.addTask(i);
}

Again , Pay attention here , Because we put time-consuming tasks in the same service Inside , So there's the problem of circular dependency , Need to use @Lazy .

test result :

2020-11-11 22:27:05.152 INFO 18888 --- [         task-3] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -146
2020-11-11 22:27:05.152 INFO 18888 --- [         task-5] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -148
2020-11-11 22:27:05.152 INFO 18888 --- [         task-4] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -147
2020-11-11 22:27:05.152 INFO 18888 --- [         task-6] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -149
2020-11-11 22:27:05.153 INFO 18888 --- [         task-7] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -150
2020-11-11 22:27:05.152 INFO 18888 --- [         task-2] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -145
2020-11-11 22:27:05.153 INFO 18888 --- [         task-8] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -151
2020-11-11 22:27:05.152 INFO 18888 --- [         task-1] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -144
2020-11-11 22:27:07.154 INFO 18888 --- [         task-6] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -149
2020-11-11 22:27:07.154 INFO 18888 --- [         task-3] c.f.s.a.s.impl.TestAsyncServiceImpl     : Calculation task -146
2020-11-11 22:27:07.154 INFO 18888 --- [nio-8080-exec-1] c.f.s.a.s.impl.TestAsyncServiceImpl     : Time consuming 4.006 s

The results page

65

Test code

https://github.com/fengwenyi/study-spring-boot/tree/master/spring-boot-async

版权声明
本文为[Feng Wenyi]所创,转载请带上原文链接,感谢

Scroll to Top