Async Processing
Take a token, sit down. The kitchen cooks your dosa in the background.
The Hyderabad Tiffin Center Token System Analogy:
At a busy Tiffin center in Ameerpet, you don’t stand at the counter for 15 minutes while they cook your dosa. You pay, take a token, and go sit down. The kitchen prepares the dosa asynchronously in the background. When it’s ready, they call your token number.
In Spring Boot, @Async is the token system. When a user calls an API, Spring Boot takes the request, hands it to a background thread pool, and immediately returns a “200 OK” to the user. The background thread does the heavy lifting.
- @EnableAsync: Placed on the main class to enable async execution.
- @Async: Placed on a method. Spring intercepts the call and runs it on a separate background thread.
- CompletableFuture<T>: The modern way to return the result of an async task. The user can check if it’s done and retrieve the result later.
First, enable Async in your main class.
package com.devinhyderabad;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync // 1. Turn on the async engine
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}// Async Service
package com.devinhyderabad;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
@Service
public class ReportService {
// 2. @Async sends this to a background thread
@Async
public CompletableFuture<String> generateHeavyReport() {
try {
System.out.println("Generating report on: " + Thread.currentThread().getName());
Thread.sleep(5000); // Simulate a 5-second heavy task
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return CompletableFuture.completedFuture("Report Generated Successfully!");
}
}
// Controller
@RestController
@RequestMapping("/api/reports")
public class ReportController {
@Autowired
private ReportService reportService;
// Returns IMMEDIATELY, does NOT wait 5 seconds
@GetMapping("/generate")
public String generateReport() {
reportService.generateHeavyReport();
return "Report generation started in the background!";
}
// Returns the actual result after 5 seconds
@GetMapping("/generate-and-wait")
public CompletableFuture<String> generateAndWait() {
return reportService.generateHeavyReport();
}
}Interview Question: “Does @Async work if you call the method from within the same class?”
Answer: No. @Async relies on Spring’s AOP proxy. If class A calls a @Async method inside class A, it bypasses the proxy and runs synchronously. The @Async method must be called from a different bean (e.g., Controller calling Service).
Enterprise Note: By default, Spring uses SimpleAsyncTaskExecutor which creates a new thread for every task (bad for performance). In production, you must define a custom Executor bean with a thread pool to limit the number of background threads and prevent system crashes.
Key Takeaways
- ✅ @EnableAsync activates async execution in Spring Boot
- ✅ @Async runs a method on a background thread, returning immediately
- ✅ CompletableFuture allows retrieving the result of an async task
- ✅ @Async only works when called from a different bean (AOP proxy requirement)
- ✅ Always define a custom Executor bean with thread pool in production
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login