Boost Spring Boot Performance: Mastering Synchronous vs Asynchronous Calls
This article explains the difference between synchronous and asynchronous method calls in Spring Boot, shows how to convert blocking tasks into @Async methods, demonstrates unit‑test setups with CompletableFuture for proper coordination, and provides complete code examples to reduce overall execution time.
What is an "asynchronous call"? An asynchronous call allows a program to continue executing subsequent statements without waiting for the called method to return a result, unlike a synchronous call where each line must wait for the previous one to finish.
Synchronous Call
A simple example illustrates a synchronous execution of three tasks, each sleeping for a random time up to ten seconds.
@Slf4j
@Component
public class AsyncTasks {
public static Random random = new Random();
public void doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:" + (end - start) + "毫秒");
}
public void doTaskTwo() throws Exception {
log.info("开始做任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务二,耗时:" + (end - start) + "毫秒");
}
public void doTaskThree() throws Exception {
log.info("开始做任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务三,耗时:" + (end - start) + "毫秒");
}
}In a unit test the AsyncTasks bean is injected and the three methods are called sequentially:
@Slf4j
@SpringBootTest
public class Chapter75ApplicationTests {
@Autowired
private AsyncTasks asyncTasks;
@Test
public void test() throws Exception {
asyncTasks.doTaskOne();
asyncTasks.doTaskTwo();
asyncTasks.doTaskThree();
}
}The log output shows each task running one after another, confirming the total execution time is the sum of the three durations.
Asynchronous Call
Because the three tasks have no inter‑dependency, they can be executed concurrently to improve efficiency. Adding the @Async annotation turns the methods into asynchronous ones.
@Slf4j
@Component
public class AsyncTasks {
public static Random random = new Random();
@Async
public void doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:" + (end - start) + "毫秒");
}
@Async
public void doTaskTwo() throws Exception {
log.info("开始做任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务二,耗时:" + (end - start) + "毫秒");
}
@Async
public void doTaskThree() throws Exception {
log.info("开始做任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务三,耗时:" + (end - start) + "毫秒");
}
}To enable the annotation, the main application class must be annotated with @EnableAsync:
@EnableAsync
@SpringBootApplication
public class Chapter75Application {
public static void main(String[] args) {
SpringApplication.run(Chapter75Application.class, args);
}
}Running the same unit test may produce various results: no output, partial output, or out‑of‑order output, because the main thread can finish before the asynchronous tasks complete. Also, methods annotated with @Async must not be static, otherwise the annotation is ignored.
Asynchronous Callback
To know when all asynchronous tasks have finished, each method can return a CompletableFuture<String>:
@Async
public CompletableFuture<String> doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:" + (end - start) + "毫秒");
return CompletableFuture.completedFuture("任务一完成");
}The test records the start time, invokes the three async methods, waits for all of them with CompletableFuture.allOf(...).join(), then calculates the total elapsed time:
@Test
public void test() throws Exception {
long start = System.currentTimeMillis();
CompletableFuture<String> task1 = asyncTasks.doTaskOne();
CompletableFuture<String> task2 = asyncTasks.doTaskTwo();
CompletableFuture<String> task3 = asyncTasks.doTaskThree();
CompletableFuture.allOf(task1, task2, task3).join();
long end = System.currentTimeMillis();
log.info("任务全部完成,总耗时:" + (end - start) + "毫秒");
}The log shows the three tasks starting concurrently and the total time being roughly the longest individual task, demonstrating the performance benefit of asynchronous execution.
Code Example
The complete project source code is available in the chapter7-5 directory of the repository:
GitHub: https://github.com/dyc87112/SpringBoot-Learning/
Gitee: https://gitee.com/didispace/SpringBoot-Learning/
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
