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.
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.
initialValue() method is used to set the initial value of
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.
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
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
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.