Skip to main content

Thread Local Storage in Java


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.
Most major programming languages have implementations of the concept. For example, C++11 has the thread local keyword, and Ruby has chosen an API approach.
Java has also an implementation of the concept with  java.lang.ThreadLocal<T> and with subclass java.lang.InheritableThreadLocal<T> since version 1.2, so nothing new and shiny here.
Let's say that for some reason we need to have a Long specific for our thread. Using Thread local that would simply be:

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();
  }

}



One possible sample run of the following code will result in:

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");
Or the current JDBC connection user credentials in UserCredentialsDataSourceAdapter. If we get back on RequestContextHolder, we can use this class to access all of the current request information from anywhere in our code. A common use case for this is  LocaleContextHolder, which 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 is a high chance we'll find it as well.

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
It is very easy to create a memory leak in your server code using ThreadLocal if it runs on an application server. ThreadLocal context is associated to the thread where it runs and will be garbaged once the thread is dead. Modern app servers use pool of threads instead of creating new ones on each request, meaning you can end up holding large objects indefinitely in your application.  Since the thread pool is from the app server, our memory leak could remain even after we unload our application. The fix for this is simple - free up resources you do not need. 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, for instance, and scheduler, he would get a very bad surprise. Even though, the variables in ThreadLocal are local to the thread they are very much global in your code. So, if you want to avoid maintenance developers hunting you down and taking their revenge, 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



Popular posts from this blog

HTML 5 data-* attributes, how to use them and why

It is always tempting to add custom attributes in HTML so that you can use the data stored there to do X. But if you do that there is no way of knowing if your HTML attribute will not be overridden in the future and used for something else and additionally you will not be writing valid HTML markup that can pass HTML 5 validator and with that you can create some very bad side effects. That is why there is a spec in HTML 5 called custom data attributes that enable number of useful features.

You may go around and read the specs, but the basic idea is very simple, you can add any attribute that starts with "data-" and that attribute will be treated as non-visible data for that attribute. By non-visible I mean that it is not something that gets rendered to the client so it does not affect the layout or style of the page, but it is there in the HTML so in no way this is private.
So let's get right into it, the following snippet is a valid HTML5 markup

<div id="aweso…

Temporary files and directories in Java 7 and before

Sometimes we want to create a temporary file, whether to save some data that gets written by some other application or just to temporary store stuff. Well, usually applications have their own temporary folder where they do this and it gets somehow configured. But why not use the underlying OS specific file like "/tmp/" in Linux so there must be some system property that has this info and there is. The key is "java.io.tmpdir" resulting in "/tmp" in my case or by code:
String tempDir = System.getProperty("java.io.tmpdir"); We can use tempDir  folder as a temporary place to store files, but there are a lot nicer ways to work with files like this even in JDK6 not just in JDK7:
import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; public class TempFile { public static void main(String[] args) { try { // create a temp file File tempFile = File.createTempFile("old-file",…

Basic Authentication with RestTemplate

Spring Rest Templates are very good way of writing REST clients. By default they work with basic HTTP so if we need to use Basic Authorization we would need to init the rest template with custom HttpClient. This way the Rest Template will automatically use Basic Auth and append to the HTTP headers "Authorization: Basic BASE64ENCODED_USER_PASS".

HttpClient client = new HttpClient(); UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("USERNAME","PASS"); client.getState().setCredentials( new AuthScope("www.example.com", 9090, AuthScope.ANY_REALM), credentials); CommonsClientHttpRequestFactory commons = new CommonsClientHttpRequestFactory(client); RestTemplate template = new RestTemplate(commons); SomeObject result = template.getForObject( "http://www.example.com:9090/",SomeObject.class );

In EE application this would probably be managed by DI framework like Spring Core and only initialized once sin…