The Problem

Java Developers of multi threaded application might feel a need to store global variables which should not be shared by multiple threads.

Example - Storing user information while handling a web request on multi threaded server.

Solution : ThreadLocal

ThreadLocal object acts as a variable container which enables you to create and maintain a global state which is tied to one thread. Each thread accessing the ThreadLocal object will have it’s own copy of underlying variable.

ThreadLocal Example

In following example,

  • Threads will create a random User Id at the start of their execution.
  • Threads will ask userIdContainer to store their respective User id.
  • After random sleep threads will again access their User Id, and because ThreadLocal ties the state to each thread, threads will get their respective User Id.

As shown in below example, ThreadLocal objects are generally used as static and final to keep the object globally accessible.

import java.util.Random;

public class ThreadLocalTest {
    public static void main(String[] args) {
        // Using Lambda to write Runnable implementation
        Runnable r = () -> {
            UserId.set("user" + new Random().nextInt(1000));
            System.out.println(Thread.currentThread().getId() 
                   + ":" +  UserId.get());

            // Sleeping for random time
            // to provide proof of overlapping statements by multiple threads
            try { Thread.sleep(new Random().nextInt(500)); } 
            catch (InterruptedException e) {}

            System.out.println(Thread.currentThread().getId() 
                  + ":" + UserId.get());
            UserId.clear();
        };

        // Creating and starting 4 threads
        new Thread(r).start();
        new Thread(r).start();
        new Thread(r).start();
        new Thread(r).start();
    }
}

class UserId {
    private static final ThreadLocal<String> userIdContainer
         = new ThreadLocal<>();

    // Returns the current thread's User Id
    public static String get() {
        return userIdContainer.get();
    }

    // Sets current thread's User Id
    public static void set(String userId) {
        userIdContainer.set(userId);
    }
    // Remove value. when no longer required
    public static void clear() {
        userIdContainer.remove();
    }
}

Output

10:user545
11:user591
12:user398
13:user149
11:user591
13:user149
12:user398
10:user545

Precautions while using ThreadLocal

  • Do not forget to clean up the ThreadLocal object’s value using remove() method when value is no longer required in further execution. It may cause Out of Memory exceptions in your application. The same issue is discussed in the stackoverflow answer

ThreadLocal’s use in Spring MVC framework

In most multi-threaded web frameworks, ThreadLocal is used internally to store HTTP request attributes throughout the life cycle of that request. One such example is org.springframework.web.context.request.RequestContextHolder. Check out the source code on Github.

Conclusion

ThreadLocal allows multi threaded Java program to manage Thread’s global state.