Understanding Synchronous and Asynchronous Calls in Spring Boot Using @Async and Future

This article explains the difference between synchronous and asynchronous method calls in Java, demonstrates how to implement synchronous tasks, convert them to asynchronous using Spring Boot's @Async annotation, and shows how to coordinate completion with Future objects and unit tests.

Top Architect
Top Architect
Top Architect
Understanding Synchronous and Asynchronous Calls in Spring Boot Using @Async and Future

In high‑concurrency web applications, asynchronous calls are often used to improve performance. The article first defines synchronous calls, where each line waits for the previous one to finish, and illustrates this with a simple

@Component public class Task { public static Random random = new Random(); public void doTaskOne() throws Exception { System.out.println("开始做任务一"); 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("开始做任务二"); 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("开始做任务三"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任务三,耗时:" + (end - start) + "毫秒"); } }

and a corresponding JUnit test that invokes the three methods sequentially.

The test output shows each task running one after another, resulting in a total execution time equal to the sum of the three individual durations.

To improve efficiency, the article introduces asynchronous execution with Spring Boot's @Async annotation. By annotating each task method and adding @EnableAsync to the main application class, the same Task class becomes:

@Component public class Task { @Async public void doTaskOne() throws Exception { /* same body as before */ } @Async public void doTaskTwo() throws Exception { /* same body as before */ } @Async public void doTaskThree() throws Exception { /* same body as before */ } }

After enabling async, running the unit test may produce no output, partial output, or out‑of‑order output because the main thread finishes before the async tasks complete. The article notes that async methods must not be static.

To reliably wait for all async tasks, the methods are changed to return Future<String>:

@Async public Future<String> doTaskOne() throws Exception { System.out.println("开始做任务一"); long start = System.currentTimeMillis(); Thread.sleep(random.nextInt(10000)); long end = System.currentTimeMillis(); System.out.println("完成任务一,耗时:" + (end - start) + "毫秒"); return new AsyncResult<>("任务一完成"); }

The test method is updated to capture the Future objects, record a start time, and poll isDone() in a loop until all three tasks finish, then compute the total elapsed time:

@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()) { break; } Thread.sleep(1000); } long end = System.currentTimeMillis(); System.out.println("任务全部完成,总耗时:" + (end - start) + "毫秒"); }

Running this test yields interleaved start messages, out‑of‑order completion messages, and finally a line showing the total time, demonstrating that asynchronous execution reduces overall runtime compared with the synchronous version.

Finally, the article reminds readers to add @EnableAsync in the main application class:

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

The tutorial concludes with a note that the content is sourced from the internet and includes promotional messages for a WeChat public account and related resources.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaunit testingSpring BootAsyncFuture
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.