// Tutorial //

Java ThreadLocal Example

Published on August 3, 2022
Default avatar
By Pankaj
Developer and author at DigitalOcean.
Java ThreadLocal Example

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Java ThreadLocal is used to create thread local variables. We know that all threads of an Object share it’s variables, so the variable is not thread safe. We can use synchronization for thread safety but if we want to avoid synchronization, we can use ThreadLocal variables.

Java ThreadLocal

ThreadLocal, Java ThreadLocal Every thread has it’s own ThreadLocal variable and they can use it’s get() and set() methods to get the default value or change it’s value local to Thread. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread.

Java ThreadLocal Example

Here is a small example showing use of ThreadLocal in java program and proving that every thread has it’s own copy of ThreadLocal variable. ThreadLocalExample.java

package com.journaldev.threads;

import java.text.SimpleDateFormat;
import java.util.Random;

public class ThreadLocalExample implements Runnable{

    // SimpleDateFormat is not thread-safe, so give one to each thread
    private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
        @Override
        protected SimpleDateFormat initialValue()
        {
            return new SimpleDateFormat("yyyyMMdd HHmm");
        }
    };
    
    public static void main(String[] args) throws InterruptedException {
        ThreadLocalExample obj = new ThreadLocalExample();
        for(int i=0 ; i<10; i++){
            Thread t = new Thread(obj, ""+i);
            Thread.sleep(new Random().nextInt(1000));
            t.start();
        }
    }

    @Override
    public void run() {
        System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern());
        try {
            Thread.sleep(new Random().nextInt(1000));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //formatter pattern is changed here by thread, but it won't reflect to other threads
        formatter.set(new SimpleDateFormat());
        
        System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern());
    }

}

Output of the above java ThreadLocal example program is:

Thread Name= 0 default Formatter = yyyyMMdd HHmm
Thread Name= 1 default Formatter = yyyyMMdd HHmm
Thread Name= 0 formatter = M/d/yy h:mm a
Thread Name= 2 default Formatter = yyyyMMdd HHmm
Thread Name= 1 formatter = M/d/yy h:mm a
Thread Name= 3 default Formatter = yyyyMMdd HHmm
Thread Name= 4 default Formatter = yyyyMMdd HHmm
Thread Name= 4 formatter = M/d/yy h:mm a
Thread Name= 5 default Formatter = yyyyMMdd HHmm
Thread Name= 2 formatter = M/d/yy h:mm a
Thread Name= 3 formatter = M/d/yy h:mm a
Thread Name= 6 default Formatter = yyyyMMdd HHmm
Thread Name= 5 formatter = M/d/yy h:mm a
Thread Name= 6 formatter = M/d/yy h:mm a
Thread Name= 7 default Formatter = yyyyMMdd HHmm
Thread Name= 8 default Formatter = yyyyMMdd HHmm
Thread Name= 8 formatter = M/d/yy h:mm a
Thread Name= 7 formatter = M/d/yy h:mm a
Thread Name= 9 default Formatter = yyyyMMdd HHmm
Thread Name= 9 formatter = M/d/yy h:mm a

As you can see from the output that Thread-0 has changed the value of formatter but still thread-2 default formatter is same as the initialized value. You can see the same pattern for other threads too. Update: ThreadLocal class is extend in Java 8 with a new method withInitial() that takes Supplier functional interface as argument. So we can use lambda expressions to easily create the ThreadLocal instance. For example, above formatter ThreadLocal variable can be defined in one line as below:

private static final ThreadLocal<SimpleDateFormat> formatter = 
	ThreadLocal.<SimpleDateFormat>withInitial
	(() -> {return new SimpleDateFormat("yyyyMMdd HHmm");});

If you are new to Java 8 features, please check out Java 8 Features and Java 8 Functional Interfaces. That’s all for ThreadLocal in java programming. Reference: API Doc


Want to learn more? Join the DigitalOcean Community!

Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.

Sign up
About the authors
Default avatar
Pankaj

author

Developer and author at DigitalOcean.

Still looking for an answer?

Was this helpful?

Hi Pankaj, When we use thread pool, do we need to call threadlocal.remove() method? I searched it via internet, but results confused me.

- Noodles

    Thank you for the article, nicely explained, but why we need to declare thread-local variable static private

    - kranthi

      How is it possible, “We can use synchronization for thread safety but if we want to avoid synchronization, we can use ThreadLocal variables.” as mentioned in the first paragraph, to avoid synchronization with ThreadLocal? I think if we use synchronization then it means that the shared resource will be accessed by only one thread at once and after that another thread take lock then that thread will get the updated value of resource(if it was updated by any thread) while in ThreadLocal resource remains same even after modifying resource in threads because it is local to thread. So, We can use ThreadLocal for resource if we want the default value of that in each thread and according to thread purpose we can modify locally and it will not impact in the main copy. Please let me know if i’m not in correct direction.

      - praveen gupta

        Fan of your all articles , but this 2 line making me confuse . 1) ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread. 2) Every thread has it’s own ThreadLocal variable and they can use it’s get() and set() methods to get the default value or change it’s value local to Thread if a Variable is static how each thread can use that variable as separate (own variable) ?

        - rahul G

          I also do not see where is that new pattern declared that is used by toPattern()

          - Andrey

            What I do not see is where ThreadLocalExample that implements Runnable starts … Thank you

            - Andrey

              The lambda expression part at the end, why do you need the “” in front of “withInitial”? I can just call ThreadLocal.withInitial(…), right? Thanks for the great articles!

              - dz

                I’m try to understand how to use the ThreadLocal class. I understand that there is a cleanup phase but this article doesn’t mention anything about it !

                - Muhammad Gelbana

                  I got the point that ThreadLocal maiitains a private kind of value respective to the threads. But in other sites too,it is given that it could be used as an alternative to synchronization,to improve performance. I just wonder,since we creating a new value(object instance) in its initial value,obviously,all the changes made to that object by that thread will be exclusive to that object only.So maintaining “thread safety”.I could get this even with Out ThreadLocal variable or Synchronized block,if i am creating a new Instance for every thread. Could some one please explain, what is special in this ThreadLocal for making its things private,isn’t it obvious? Couldn’t i get same thing,by making separate objects,without ThreadLocal and achieve this thread safety?

                  - Sriharsha

                    Very good article. Below are my comments : This is not required and not in use. protected SimpleDateFormat initialValue() { return new SimpleDateFormat(“yyyyMMdd HHmm”); } Instead this is required : formatter.set(new SimpleDateFormat(“yyyyMMdd HHmm”));

                    - yogi g