Thread part 1: Thread for client handing request
Thread part 1: Thread for client handing request
01. Request → Thread Mapping
When a request arrives, Spring Boot (via an embedded servlet container like Tomcat) assigns it to a thread from a thread pool (like the Tomcat thread pool).
Each thread handles one request at a time.
This thread is often called a worker thread.
02. ThreadLocal for Request-Specific Data
ThreadLocal is used to store data that should be accessible throughout the request without passing it explicitly.
Spring Security and frameworks like Sleuth (for logging) use this under the hood.
However, ThreadLocal should be cleared manually or with proper filters/interceptors to avoid memory leaks in thread pools (since threads are reused).
03. ThreadLocal Automatically Not Cleared (Reasons have been explain at the end)
If you use ThreadLocal, you must call .remove() after the request is done (or in a filter/interceptor).
Spring Security and others manage their own cleanup.
java
threadLocal.remove(); // Important when using ThreadLocal
05. Where is User Auth Data Stored?
Spring Security stores user authentication (principal) data in a ThreadLocal using SecurityContextHolder.
How it works:
When a request comes with a JWT (or other auth token):
A filter (like JwtAuthenticationFilter) validates it.
Then Spring sets the authenticated user info using:
SecurityContextHolder.getContext().setAuthentication(authentication);
This info is stored in a ThreadLocal for that request thread.
You can retrieve it from anywhere in your code (as long as it's in the same thread):
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String username = auth.getName(); // Get logged-in username
Once the request is completed, Spring Security clears the SecurityContext automatically using a filter (SecurityContextPersistenceFilter).
Bonus Tips
To implement your own data-carrying logic across the request:
Use RequestContextHolder or ThreadLocal.
Or use Spring AOP / custom filters / interceptors to inject/remove data.
RequestContextHolder
It's a Spring utility that lets you access the current HTTP request or store request-scoped data.
Internally, it uses a ThreadLocal under the hood.
Example:
ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attrs.getRequest();
Spring uses a filter called RequestContextFilter or DispatcherServlet which automatically:
Sets the RequestAttributes when request starts
Clears it when the request ends
If we added our own data.. those should clear manually
Ex: RequestContextHolder.setRequestAttributes(attrs);
In this case, you should also call:
RequestContextHolder.resetRequestAttributes();
Thread local values are not automatically. Why is that ?
1. Thread pool is initialized
A fixed number of threads are created and reused to handle requests.
2. Request A comes in
It is assigned to Thread-1.
3. You store data using ThreadLocal
Example:
ThreadLocal<MyData> threadLocal = new ThreadLocal<>();
threadLocal.set(myData);
Each thread has an internal map to hold this data.
4. Request A finishes
But Thread-1 is not destroyed — it goes back to the pool and stays alive.
5. If you didn’t call threadLocal.remove(),
the data (myData) still stays in Thread-1’s internal map.
6. Request B is assigned to the same Thread-1
It might accidentally see the old data from Request A.
Even if you set new data, the old one remains in memory, wasting space.
7. Why can’t the Garbage Collector clean it?
The ThreadLocal key is a weak reference (can be GC'd).
But the value (myData) is still strongly referenced by the thread’s internal map.
So the value stays in memory — causing a memory leak.
Best Practice:
try {
threadLocal.set(myData);
// do work
} finally {
threadLocal.remove(); // clean up after request
}
Comments
Post a Comment