Asynchronous invocation is almost a panacea for dealing with the performance problems of highly concurrent Web applications, so what is “asynchronous invocation”?

“Asynchronous invocation” corresponds to “synchronous invocation”. Synchronous invocation means that programs are executed in a defined order. Each line of programs must wait for the completion of the previous line of programs to be executed. Asynchronous invocation refers to the sequential execution of a program without waiting for the result of the asynchronous invocation.

A synchronous invocation

Here is a simple example to get an intuitive understanding of what synchronous calls are:

Define Task class, create three processing functions to simulate three tasks, operation time is randomly selected (within 10 seconds)

@Component public class Task { public static Random random =new Random(); Public void doTaskOne() throws Exception {system.out.println (" Start doing task 1 "); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println(" + (end-start) + "); } public void doTaskTwo() throws Exception {system.out.println (" start doing task 2 "); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println(" end - start + "); } public void doTaskThree() throws Exception {system.out.println (" start doing task three "); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println(" finish task 3, time: "+ (end-start) +" milliseconds "); }}Copy the code

In the unit test case, the Task object is injected and the three functions doTaskOne, doTaskTwo, and doTaskThree are executed in the test case.

@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class) public class ApplicationTests { @Autowired private Task task; @Test public void test() throws Exception { task.doTaskOne(); task.doTaskTwo(); task.doTaskThree(); }}Copy the code

When you execute the unit test, you see output similar to the following:

Start task 1 complete task 1:4,256 milliseconds Start Task 2 Complete Task 2:4,957 milliseconds Start Task 3 Complete Task 3:7,173 millisecondsCopy the code

DoTaskOne, doTaskTwo, and doTaskThree have been executed sequentially.

The asynchronous call

Although the above synchronous invocation successfully executed the three tasks, it can be seen that the execution time is relatively long. If there is no dependency between the three tasks and they can be executed concurrently, the execution efficiency of synchronous invocation is relatively poor. Therefore, asynchronous invocation can be considered for concurrent execution.

In Spring Boot, we can simply change a synchronous function to an asynchronous function by using the @async annotation, and change the Task class to the following mode:

@Component public class Task {@async public void doTaskOne() throws Exception {// Same as above, Ellipsis} @async public void doTaskTwo() throws Exception { } @async public void doTaskThree() throws Exception {// same content, omit}}Copy the code

In order for the @async annotation to work, you also need to configure @enableAsync in the Spring Boot main program, as follows:

@SpringBootApplication @EnableAsync public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); }}Copy the code

At this point, you can run unit tests repeatedly, and you may encounter different results, such as:

  • There is no task-related output
  • There are partial task-specific outputs
  • Out-of-order task-related output

The reason is that the doTaskOne, doTaskTwo, and doTaskThree functions are executed asynchronously. After the main program is called asynchronously, the main program does not care whether the execution of these three functions is complete. Because there is no other content to be executed, the program will automatically end, resulting in incomplete or no output task related content.

Note: Do not define @async functions as static, so asynchronous calls do not take effect

An asynchronous callback

In order for doTaskOne, doTaskTwo, and doTaskThree to complete properly, suppose we need to count the total time required for the concurrent execution of the three tasks. We need to record the time and calculate the result after all the three functions are completed.

So how do we determine if the above three asynchronous calls have completed? We need to use the Future to return the result of the asynchronous call, like modifying the doTaskOne function as follows:

@async public Future<String> doTaskOne() throws Exception {system.out.println (" start doing task 1 "); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println(" + (end-start) + "); Return new AsyncResult<>(" task completed "); }Copy the code

After modifying the other two asynchronous functions as described above, let’s modify the test case so that the test does something else after waiting for three asynchronous calls.

@Test public void test() throws Exception { long start = System.currentTimeMillis(); Future<String> task1 = task.doTaskOne(); Future<String> task2 = task.doTaskTwo(); Future<String> task3 = task.doTaskThree(); While (true) {if(task1.isdone () && task2.isdone () && task3.isdone ()) {// All three tasks are called, and the loop is broken; } Thread.sleep(1000); } long end = System.currentTimeMillis(); System.out.println(" end - start + "); }Copy the code

See what changes we’ve made:

  • Record the start time at the beginning of the test case
  • When three asynchronous functions are called, the result object of type Future is returned
  • After three asynchronous functions are called, a loop is opened to determine whether all three asynchronous functions are finished based on the Future object returned. If both end, the loop ends; If not, wait 1 second before judging.

After exiting the loop, calculate the total time required for the three tasks to be executed concurrently based on the end time and start time.

Run the unit test above and see the following results:

Start Task 1 Start Task 2 Start Task 3 Complete Task 3 in 37ms. Complete Task 2 in 3661 ms. Complete Task 1 in 7149 ms. Complete all tasks in 8025 msCopy the code

As you can see, by making asynchronous calls, tasks one, two, and three execute concurrently, effectively reducing the total running time of the program.

(Thanks for reading, hope you all help)

Source: blog.csdn.net/weixin_34186931/article/details/89564480


Recommend 3 original Springboot +Vue projects, with complete video explanation and documentation and source code:

Build a complete project from Springboot+ ElasticSearch + Canal

  • Video tutorial: www.bilibili.com/video/BV1Jq…
  • A complete development documents: www.zhuawaba.com/post/124
  • Online demos: www.zhuawaba.com/dailyhub

【VueAdmin】 hand to hand teach you to develop SpringBoot+Jwt+Vue back-end separation management system

  • Full 800 – minute video tutorial: www.bilibili.com/video/BV1af…
  • Complete development document front end: www.zhuawaba.com/post/18
  • Full development documentation backend: www.zhuawaba.com/post/19

【VueBlog】 Based on SpringBoot+Vue development of the front and back end separation blog project complete teaching

  • Full 200 – minute video tutorial: www.bilibili.com/video/BV1af…
  • Full development documentation: www.zhuawaba.com/post/17

If you have any questions, please come to my official account [Java Q&A Society] and ask me