Java Thread Local Storage explained in easiest practical way

Java Thread Local Storage

One of the cool feature of Java that I like is ThreadLocal storage. ThreadLocal storage is explained in easiest way with practical example in this blog.

ThreadLocal is a class in java.lang package which provides a way to store and access data of any type per thread, which means each thread will have it's separate instance of the data. During execution of a thread, one class can set data in ThreadLocal and other classes further down in the execution layer can access/read the data, as long as execution in within same thread. It is important to know that ThreadLocal data set by one thread is not visible or accessible in another thread. That the core concept of ThreadLocal storage.

The way to use ThreadLocal is declare a static property of type ThreadLocal where T is type of the data we want to store. It's static so that it easily accessible in classes wherever needed. You can declare it public, private or whatever make sense in your usecase. Usually declaring it as public make sense.

Since the way ThreadLocal storage works, it must be used carefully. To avoid incorrect use of ThreadLocal by mistake, it is good idea to declare ThreadLocal variables in a separate class and name the class appropriate to call it out load.

Once declared you can set data into ThreadLocal variable
AppThreadLocal.USER_CONTEXT.set(userContext);
And to read data from ThreadLocal variable
UserContext userContext = AppThreadLocal.USER_CONTEXT.get();
Lets see the practical use of ThreadLocal variable. Use case is in practical when we write service API, we need the UserContext (calling user's userId, name, may roles as well) available in all layer's (API, Service, Facade, DAO etc). One way to make UserContext available in all these layers is to pass UserContext as parameter in all methods starting from top to the bottom most layer, which sounds like over kill and cluttering you method signature. ThreadLocal is best fit in such situation. At the first layer we can put UserContext in a public static ThreadLocal variable, access and it in all layer's further down during execution, once execution is done, remove it from ThreadLocal.

Lets see how does the code look like to implement this.

UserContext is the class whose instance we want to store in ThreadLocal Storage
The class where we defined ThreadLocal variable
The Thread which sets UserContext in ThreadLocal variable, calls service api (where UserContext will be read from ThreadLocal) and once done remove data from ThreadLocal variable.
Its the service class which reads UserContext from ThreadLocal and just print it. If this calls further calls Facade or DAO, UserContext can be read there in exact same way.
Finaly the main program. It creates 2 different UserContext instances, creates two threads and pass each UserContext to them and start both threads.
In the output you can see that service method executed by tommy-Thread is getting Tom's UserContext and service method executed by jerry-Thread is getting Jerry's UserContext.

 

Note - 

It is important to remove data from ThreadLocal specially in case if your code is running under a managed container like Application Server. Because containers usually implement thread pool to process request, after processing the thread is release back to thread pool and will be used to processed other upcoming requests. Which means data set in ThreadLocal variable by first request will be available to other requests processed by same thread. Which is not correct. Also if the data put into ThreadLocal is big in size, it may lead to memory leak because thread will always remain alive in the pool and data object in ThreadLocal plus any other objects referenced by it will never become eligible for garbage collection.

The power comes will responsibility so always use ThreadLocal responsibly to avoid trouble.

Download Code

https://github.com/rakeshprajapati1982/thread-local

It you found this blog helpful please share. Any question or comments are always welcome.



Comments

Other Popular Posts

How to enable JPA eclipselink logging in WAS Liberty

EhCache3 as JCache (JSR-107) Implementation with Cache Statistics

Lambda Expression v/s Anonymous Inner Class - Java 8

EhCache3 In Memory Caching for Performance Improvement