What is ThreadLocal in Java, where will you use this class

Carvia Tech | May 05, 2019 | 4 min read | 103 views | Multithreading and Concurrency


ThreadLocal provides a mechanism of maintaining thread confinement for a given object. which allows you to associate a per-thread value with a value-holding object.
ThreadLocal Java Docs

ThreadLocal class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable.

Pattern to use ThreadLocal

ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

For example, the class below generates counters local to each thread. A new copy ThreadLocalCounter is assigned the first time it invokes ThreadLocalCounter.get() and remains unchanged on subsequent calls.

ThreadLocalCounter class
public class ThreadLocalCounter {
    private int count;

    public ThreadLocalCounter(int count) {
        this.count = count;
    }

    public int increment() {
        return ++count;
    }

    private static final ThreadLocal<ThreadLocalCounter> threadLocal = ThreadLocal.withInitial(() -> new ThreadLocalCounter(0));

    public static ThreadLocalCounter get() {
        return threadLocal.get();
    }
}

This ThreadLocalCounter can be used by multiple threads to keep their own counter copy which is not visible to other threads.

ThreadLocalCounter
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        ThreadLocalCounter threadLocalCounter = ThreadLocalCounter.get();
        while(true) {
            final int counter = threadLocalCounter.increment();
            doSomeWork(counter);
        }
    }

    private void doSomeWork(int counter) {
        //Dummy Work
    }
});
thread.start();
Garbage Collection Behaviour

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of thread-local instances are subject to garbage collection (unless other references to these copies exist).

Benefits of using ThreadLocal

  1. It makes multi-threading easy by not sharing the state of an object across threads. Since state is not shared so you don’t need to synchronize it with other requests. Please be noted that ThreadLocal is not a substitute of synchronization, instead it isolates an object from being exposed to multiple threads. Something like this:

    Servlet filter with ThreadLocal
     doGet(HttpServletRequest req, HttpServletResponse resp) {
       User user = getLoggedInUser(req);
       StaticClass.getThreadLocal().set(user)
       try {
         doSomething()
         doSomethingElse()
         renderResponse(resp)
       }
       finally {
         StaticClass.getThreadLocal().remove()
       }
     }

    Now any code that requires access to current user object, can obtain the reference using below code:

    User user = StaticClass.getThreadLocal().get()
    where Static class is defined as:
    class StaticClass {
      static private ThreadLocal threadLocal = new ThreadLocal<User>();
    
      static ThreadLocal<User> getThreadLocal() {
        return threadLocal;
      }
    }

Usecase

  1. ThreadLocal is ideal for storing objects that are not thread-safe and object sharing across threads is not required. A good example is Hibernate Session which is not threadsafe and must not be shared across threads, so we can put Session into ThreadLocal and execute the transaction. In a servlet environment, this can happen in a filter which creates a new session for each request and commit the session after request is complete. Similar approach can be taken for JDBC connection.

  2. SimpleDataFormat is not a thread-safe class, so you can use ThreadLocal to keep a copy of it per thread, thus avoiding the need for synchronization. The other option could be to create a new object on each invocation which requires more resources compared to ThreadLocal approach.

    ThreadSafeDateFormat
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    public class ThreadSafeDateFormat {
        //SimpleDateFormat is not thread-safe, so give one instance to each thread
        private static final ThreadLocal<SimpleDateFormat> formatter = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy.MM.dd HHmm a"));
    
        public static String formatIt(Date date) {
            return formatter.get().format(date);
        }
    
        public static void main(String[] args) {
            final String formatIt = ThreadSafeDateFormat.formatIt(new Date());
            System.out.println("formatIt = " + formatIt);
        }
    }
  3. ThreadLocal is very useful in web applications, a typical pattern is to store the state of web request in ThreadLocal (usually in a servlet filter or spring interceptor) at the very start of the processing and then access this state from any component involved in request processing. Normally all the processing of a web request happens in a single thread. In-fact ThreadLocal is widely used in implementing application frameworks. For example, J2EE containers associate a transaction context with an executing thread for the duration of an EJB call. This is implemented using a static Thread-Local holding the transaction context.

  4. In creating a application that requires thread level stats collections for e.g. stress testing apps, performance monitoring app.

Issues with ThreadLocal

  1. ThreadLocal introduces hidden coupling among classes, which makes them hard to test and debug. So it should be used with care.

  2. It is easy to abuse ThreadLocal by treating its thread confinement property as a license to use global variables or as a means of creating “hidden” method arguments.

References

  1. Java Concurrency in Practice: Where author (Joshua Bloch) explains how Thread confinement is one of the simplest ways to achieve thread safety and ThreadLocal is more formal means of maintaining thread confinement.

  2. Discussion on SO - https://stackoverflow.com/questions/817856/when-and-how-should-i-use-a-threadlocal-variable


Top articles in this category:
  1. What is Deadlock in Java? How to troubleshoot and how to avoid deadlock
  2. What is Immutable Class. Why would you choose it? How would you make a class immutable?
  3. Design an Immutable class that has an java.util.Date member
  4. How will you implement your custom threadsafe Semaphore in Java
  5. What is purpose of Collections.unmodifiableCollection
  6. What do you understand by Java Memory Model?
  7. what are Key classes in java.util.concurrent package



Find more on this topic:
Core Java image
Core Java

Core Java - OOP Concepts, Garbage Collection, Multi-threading, Collections Framework, Java 8 Features, Lambda Functions, Streams.

Last updated 1 week ago


Recommended books for interview preparation:

This website uses cookies to ensure you get the best experience on our website. more info