Java ThreadLocal

Java ThreadLocal class enables developer to create variables that can only be read and written by the same thread. Thus, even if two threads are executing the same code and the code has a reference to the same ThreadLocal variable, the two threads cannot see each other’s ThreadLocal variables.

ThreadLocal instance is created using new operator –

private ThreadLocal threadLocal = new ThreadLocal();

Once a ThreadLocal instance is created, the value to be stored in it can be set using set() method –

threadLocal.set("A thread local value");

Stored value is read via get() method. Below is example :

String threadLocalValue = (String)threadLocal.get();

It is possible to remove a value set in a ThreadLocal variable – by calling remove() method :

threadLocal.remove()

ThreadLocal can be created with a generic type. Using a generic type only objects of the generic type can be set as value on the ThreadLocal. Also, there will be no need to typecast the value returned by get() :

private ThreadLocal<String> myThreadLocal = new ThreadLocal<>();
myThreadLocal.set("Hello ThreadLocal");
String threadLocalValue = myThreadLocal.get();

It is possible to set an initial value for a Java ThreadLocal which will be used the first time get() is called – before set() has been called with a new value. There are two options for specifying an initial value for a ThreadLocal :

  • Create a ThreadLocal subclass that overrides the initialValue() method
  • Create a ThreadLocal with a Supplier interface implementation

The easiest way to create a subclass of ThreadLocal is to simply create an anonymous subclass and override initialValue() method :

private ThreadLocal myThreadLocal = new ThreadLocal<String>() {
    @Override
    protected String initialValue() {
        return String.valueOf(System.currentTimeMillis());
    }
}

Note that different Threads will still see different initial values. Each thread will create its own initial value.

The second method for specifying an initial value for a Java ThreadLocal variable is to use its static factory method withInitial(Supplier) passing a Supplier interface implementation as a parameter. Here is an example :

ThreadLocal<String> threadLocal = ThreadLocal.withInitial(new Supplier<String>() {
    @Override
    public String get() {
        return String.valueOf(System.currentTimeMillis());
    }
});

Since Supplier is a functional interface, it can be implemented using a Java Lambda Expression. Here is how it looks :

ThreadLocal threadLocal = ThreadLocal.withInitial( () -> String.valueOf(System.currentTimeMillis()) );

In some situations developer cannot use the standard ways of setting an initial value. In that case, initial value can be set later, when needed. This is called Lazy Setting of ThreadLocal Value.

Next

Leave a Reply

Your email address will not be published. Required fields are marked *