JDK 1.2 introduced ThreadLocal
class to maintain the thread’s local state. A thread may need to share some state with the classes in which it runs and a thread may have its own local state. To maintain such state in the thread-scope, ThreadLocal
can be used instead of declaring the state in the Thread class and using synchronization to share it.
Many values such as the transaction id, user details, authentication and authorization details, database connection may need to be maintained and shared within a single thread. They can be stored in the ThreadLocal
. The Java EE application servers use ThreadLocal
to maintain the transaction context in EJBs.
The ThreadLocal has a subclass InheritableThreadLocal
which allows the child threads to inherit its values.
ThreadLocal
should not be used for storing global variables or to share method arguments.
If the ThreadLocal
creates new instances for values, they become implicitly thread-safe since they are not shared by more than one thread. Synchronization needs to be taken care while using shared instances such as pooled database connections.
The initialValue()
method is used to set the initial value of ThreadLocal
. The set()
and get()
methods are used to set and get the values respectively. The remove()
method introduced in Java 5 removes the ThreadLocal
instance from the thread. Once a ThreadLocal
is removed it can be garbage collected. Always ensure to explicitly remove the ThreadLocal
instances or set their value to null to avoid memory leak.
A map of ThreadLocal
weak reference as key and its value as value is maintained for each thread. The reference to a ThreadLocal
is held as long as the thread is alive. As soon as the thread is dead, its instances of ThreadLocal
are eligible for garbage collection. The memory allocated to these ThreadLocal
instances is guarenteed to be reclaimed when the memory runs out of space.
While using ThreadLocal
you may need to define multiple typed ThreadLocal<T>
classes if you wish to store typed information or you can simply use a single ThreadLocal<Object>
class to encapsulate state of various types. You can create multiple instances of ThreadLocal
to store multiple state or you can store multiple state in a single POJO class and add it as a value in ThreadLocal
(saving a Context Object within a ThreadLocal
).
Unfortunately, multiple issues of memory leaks have been reported in Tomcat and JBoss 1.2 with the use of ThreadLocal
in the Java EE applications. Application servers usually use pooled threads for better performance instead of creating a new thread for serving client requests. Due to the pooling of threads, its ThreadLocal
instances were not garbage collected leading to memory leak. There was also a memory leak when a ThreadLocal instance used another ThreadLocal instance as value.
With memory leaks, the application servers failed to reclaim the memory allocated to ThreadLocal
instances or they were not garbage collected which resulted either in OutOfMemoryError
or slowness of the application. The issues occurred when the application was redeployed multiple times in the application server. The heap dump had to be obtained and analyzed to identify the issues.
Most of the memory leaks are now identified by Tomcat and fixed in version 7.0.6 and later.
When to use ThreadLocal?
A single thread is used when a request is dispatched through multiple web components. The state variables local to a thread can be maintained in request scope. To share state in request scope in a web application, the ServletRequest
attributes can be used.
Context Object, a Core J2EE design pattern, can be used to encapsulate the state and share it in in request scope in a web application. Sharing state by using request attributes should be preferred instead of using ThreadLocal. Unlike ThreadLocal, there is no need to explicitly remove the state from request scope when its use is over while using these attributes to avoid the possibility of memory leaks.
Request Context POJO strategy is commonly used to share state which is local to a thread for e.g. ActionForm
in Struts. Using Request Context POJO strategy is a more elegant approach to maintain thread’s local state in request scope instead of using ThreadLocal
.
The Struts Framework provides ActionForm
(Request Context POJO strategy) and DynaActionForm
(Hybrid Request Context POJO strategy) to share the state by a thread in request scope.
ThreadLocal can be used to share state in class and application scope but such use of ThreadLocal to share global state is discouraged.
Using ThreadLocal in a web component should be avoided. However, the third-party APIs used in a web application may use ThreadLocal.
ThreadLocal should only be used in applications which do not provide any way to maintain local variables for a thread.