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+, etc!
It was also republished under https://www.voxxed.com/blog/2014/12/thread-local-storage-in-java/
One of the rarely known features in Java among developers is Thread-local storage. The idea is simple, and the need for it comes in scenarios where we need data that is, well, local for the thread. For example, if we have two threads that refer to the same global variable but we want them to have separate values 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
In the beginning the value is set to null to both threads, obviously each of them works with separate values since after setting the value to System.nanoTime() on Thread-0 it will not have any effect on the value of Thread-1 exactly as we wanted, a thread scoped long variable. 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 demonstrated by a simple GitHub search. Most of the usages are related to the current 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<RequestAttributes> requestAttributesHolder =
new NamedThreadLocal<RequestAttributes>("Request attributes");
Thread Locals and Memory Leaks
Now that we've learned about this awesome little feature, let's use it all over the place! Well, we can do that, but if you try a few Google searches, you'll find that most posts out there claim that ThreadLocal is evil. That's not exactly true. It's a nice utility, but in some contexts, you could easily accidentally 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
More info on the topic
http://en.wikipedia.org/wiki/Thread-local_storagehttp://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