One of the rarely known features among developers is Thread-local storage. The idea is simple and need for it comes in scenarios where we need data that is … well local for the thread. If we have two threads we that refer to the same global variable but we wanna them to have separate value independently initialized of each other.
public class ThreadLocalExample {
public static class SomethingToRun implements Runnable {
private ThreadLocal threadLocal = new ThreadLocal();
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
}
threadLocal.set(System.nanoTime());
System.out.println(Thread.currentThread().getName() + " " + threadLocal.get());
}
}
public static void main(String[] args) {
SomethingToRun sharedRunnableInstance = new SomethingToRun();
Thread thread1 = new Thread(sharedRunnableInstance);
Thread thread2 = new Thread(sharedRunnableInstance);
thread1.start();
thread2.start();
}
}
Thread-0 null
Thread-0 132466384576241
Thread-1 null
Thread-1 132466394296347
One nice side effect is a case where the thread calls multiple methods from various classes. They will all be able to use the same thread scoped variable without major API changes. Since the value is not explicitly passed through one might argue it difficult to test and bad for design, but that is a separate topic altogether.
In what areas are popular frameworks using Thread Locals?
Spring being one of the most popular frameworks in Java uses ThreadLocals internally for many parts, easily shown by a simple github search. Most of the usages are related to the current’s user’s actions or information. This is actually one of the main uses for ThreadLocals in JavaEE world, storing information for the current request like in RequestContextHolder :
private static final ThreadLocal requestAttributesHolder =
new NamedThreadLocal<RequestAttributes>("Request attributes");
If we get back on RequestContextHolder we can use this class to access all of the current request information for anywhere in our code.
Common use case for this is LocaleContextHolder that helps us store the current user’s locale.
Mockito uses it to store the current “global” configuration and if we take a look at any framework out there there is a high chance we’ll find it as well.
Thread Locals and Memory Leaks
We learned this awesome little feature so let’s use it all over the place. We can do that but few google searches and we can find out that most out there say ThreadLocal is evil. That’s not exactly true, it is a nice utility but in some contexts it might be easy to create a memory leak.
“Can you cause unintended object retention with thread locals? Sure you can. But you can do this with arrays too. That doesn’t mean that thread locals (or arrays) are bad things. Merely that you have to use them with some care. The use of thread pools demands extreme care. Sloppy use of thread pools in combination with sloppy use of thread locals can cause unintended object retention, as has been noted in many places. But placing the blame on thread locals is unwarranted.” – Joshua Bloch
One other ThreadLocal misuse is API design. Often I have seen use of RequestContextHolder(that holds ThreadLocal) all over the place, like the DAO layer for example. Later on if one were to call the same DAO methods outside a request like and scheduler for example he would get a very bad surprise.
This create black magic and many maintenance developers who will eventually figure out where you live and pay you a visit. Even though the variables in ThreadLocal are local to the thread they are very much global in your code. Make sure you really need this thread scope before you use it.
More info on the topic
http://en.wikipedia.org/wiki/Thread-local_storage
http://www.appneta.com/blog/introduction-to-javas-threadlocal-storage/
https://plumbr.eu/blog/how-to-shoot-yourself-in-foot-with-threadlocals
http://stackoverflow.com/questions/817856/when-and-how-should-i-use-a-threadlocal-variable
https://plumbr.eu/blog/when-and-how-to-use-a-threadlocal
https://weblogs.java.net/blog/jjviana/archive/2010/06/09/dealing-glassfish-301-memory-leak-or-threadlocal-thread-pool-bad-ide
https://software.intel.com/en-us/articles/use-thread-local-storage-to-reduce-synchronization
This post is part of the Java Advent Calendar and is licensed under the Creative Commons 3.0 Attribution license. If you like it, please spread the word by sharing, tweeting, FB, G+ and so on!
Author: Mite Mitreski
Mite Mitreski works on custom application development and consultancy with primary focus on Java and JVM-based solutions Currently he is working for Klarna in Stockholm on the klarna checkout and it the past he has been JUG Leader of Java User Group, Macedonia. Mite has a great passion for free and open source software, open data formats, and the open web. At the moment is also involved in the development of JSON-P as part of JSR 374.
More on my blog