Spring MVC supports asynchronous request processing so a long-running operation doesn't tie up a servlet container thread for its entire duration. Instead of blocking, the request-handling thread is released and the response is completed later on a separate thread.
Key Points: • A controller method can return Callable<T>, which Spring executes on a task executor while freeing the original request thread. • DeferredResult<T> lets the controller hand off completion to an external event, such as a message arriving from another service, without Spring managing the thread itself. • WebAsyncTask wraps a Callable with additional configuration like a timeout and a custom executor. • @Async on a service method, combined with @EnableAsync, runs that method on a separate thread pool, often paired with a CompletableFuture return type. • These strategies improve throughput under high concurrency by letting the servlet container's limited thread pool serve more requests instead of blocking on slow I/O.
Example: A reporting endpoint that queries a slow external system could return a DeferredResult immediately, then complete it once the external call finishes, allowing the server to handle other requests in the meantime instead of blocking a thread for the whole duration.
Code Example:
@GetMapping("/report")
public DeferredResult<Report> getReport() {
DeferredResult<Report> result = new DeferredResult<>(5000L);
reportService.generateAsync(report -> result.setResult(report));
return result;
}Interview Tip: A concise interview answer is:
"For async processing I'd use Callable or DeferredResult from a controller method to free up the request thread while a long operation completes elsewhere, or WebAsyncTask if I need a timeout and custom executor. For background service work I'd reach for @Async with @EnableAsync, often returning a CompletableFuture."