Java Concurrency Interview

Concurrency in real systems question 125 of 180 mid

Which thread runs a Spring @Async method, and what does it lose?

@Async returns immediately and runs the method on the TaskExecutor bean. Three things do not travel with it, and all three are ThreadLocal-based: the transaction bound to the calling thread, the SecurityContext, and anything request-scoped, including the MDC values your logs correlate on.

The defaults are the part to warn about, and there are three of them. Plain Spring Framework with no executor bean falls back to SimpleAsyncTaskExecutor, which starts a thread per call and never refuses one, so a burst is an outage. Spring Boot auto-configures a ThreadPoolTaskExecutor instead, but its defaults are eight core threads and an unbounded queue, which replaces the thread explosion with a silent backlog. Since Boot 3.2, spring.threads.virtual.enabled=true makes it a virtual thread per task.

So define your own: a ThreadPoolTaskExecutor with a bounded queue and a rejection policy you chose, plus a TaskDecorator or DelegatingSecurityContextAsyncTaskExecutor if the context has to travel.

Two more traps worth naming: @Async on a method called from inside the same bean does nothing, because the proxy is bypassed, and a void @Async method throws into the void unless you return CompletableFuture or register an AsyncUncaughtExceptionHandler.

spring executors

Quiz yourself on Concurrency in real systems Suggest a correction