Per-thread local store in Java

Most examples out there in Googleland burden you with a complex piece of code creating different threads to show you how this works. That grossly obfuscates the tiny amount of code you really need and makes it nearly impossible to dig out the important bits, which are:

  1. a class creating a static ThreadLocal instance easily shared between two types of callers:
  2. a class and (likely one) method in your code that knows what per-thread data to record, and
  3. (probably multiple) classes and methods that wish to consume that per-thread data.

These three touch points, each implemented by a single line of code, are conveniently highlighted in the code below and in the order I have just listed them.

OurPerThreadValue.java

Here's the per-thread data we want to keep for use up and down our execution hierarchy. Let's say an integer right now, but we could make it an entire class instance if we wanted to.

package com.tls;

public class OurPerThreadValue
{
  public static ThreadLocal< Integer > value = new ThreadLocal<>();
}

SomeCodeSomewhere.java

In this class (and method), we know we're at the top of our execution hierarchy and we've just discovered a value we want to remember, but we don't want to have to pass it down through every method call all the way to the bottom where we end up using it.

 

The magic that's going to make this happen—and guarantee other threads executing this same code will have their own, differentiated values set by this method—is Java's own...

java.lang.ThreadLocal< T >

package com.code;

import com.tls.OurPerThreadValue;

public class SomeCodeSomewhere
{
  public void someMethod()
  {
    int value;

    /* Executing my logic here, I get an integer value of 9 that
     * I want my thread--no matter how deep in my class hierarchy
     * it goes--to remember.
     */
    value = 9;
    OurPerThreadValue.value.set( value );
    ...
    callDownDeeplyInCodeSomewhere();
  }
}
SomeClassUsedDeepDown.java

This code exemplifies some deep, dark method where we needed to know that memorable value stored on our thread. (Other threads executing this code would see their own value and not our 9.

package com.code;

import com.tls.OurPerThreadValue;

public SomeClassUsedDeepDown
{
  public void calledFromCallerCalledFromAnotherCallerCalledFromWayUp()
  {
    /* Now, what was that value that our caller wanted me
     * to print out?
     */
    int value = OurPerThreadValue.value.get();
    System.out.println( "Our per-thread value: " + value );
  }
}

Output

Of course, this is simply...

Our per-thread value: 9