Tutorial

Java ThreadLocal Example

Published on August 3, 2022
author

Pankaj

Java ThreadLocal Example

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

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the author(s)

Category:
Tutorial
Tags:

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.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
January 16, 2014

Very nice post. Helped me understand. Thanks.

- Shashank

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    February 22, 2014

    Hi Pankaj, I want to tell you, I follow your posts, I study them. But this post example is not good one. Can you come up with some better example to explain about ThreadLocal class. Thanks in advance!

    - Pankaj Chopra

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    February 23, 2014

    The examples are meant to be simple for clear understanding, like in here I am using ThreadLocal<SimpleDateFormat> to showcase that they are local to the thread and even if it’s changed by one of the thread, the other threads remains unaffected. If you have something that you think would be a good example, let me know and I will try to extend the post to include that too.

    - Pankaj

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      April 8, 2014

      I think the best example is to read JDK source code, ThreadLocal is maintained by each thread self, it is a map

      - ryan

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        May 5, 2014

        hi, formatter is final, how could change its value via set() method?

        - jeffrey

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        May 5, 2014

        formatter is final but we can call it’s setter methods. It’s not immutable.

        - Pankaj

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          August 20, 2015

          One interesting point about ThreadLocal variable is the global access. Any thread local variable is global to the thread. It can be accessed anywhere from the thread. If, from a thread several methods residing in different classes are called, thread local variable will be visible to all those methods. There is no need to pass the thread local variable as a parameter. At the same time any thread local variable is local to a thread. If there are 10 threads spawned all the 10 threads will have their own thread local variable. One thread can not access/modify other thread’s Thread Local variables.

          - infoj

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          October 6, 2015

          Can you give an example or point me to an example of how to access the thread local variable from methods in different classes?

          - michael

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          July 26, 2016

          class { static Tl tl=new Tl(); in that class tl.set(object); tl.get()–return object }

          - ganesh

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            March 22, 2016

            Hi sir, can u give some instances where this could be practically used.I mean wait and notify could be used for Consumer-Producer problems,similarly,where is this concept generally used.

            - Sriharsha

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              June 10, 2016

              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

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              June 10, 2016

              initialValue() method is providing the initial value. You can see from the output that every thread starts with default value of formatter “yyyyMMdd HHmm” even though other threads are changing it’s value to “M/d/yy h:mm a” in formatter.set(new SimpleDateFormat());.

              - Pankaj

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                September 13, 2016

                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

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  October 16, 2016

                  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

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    July 12, 2017

                    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

                      JournalDev
                      DigitalOcean Employee
                      DigitalOcean Employee badge
                      July 16, 2017

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

                      - Andrey

                        JournalDev
                        DigitalOcean Employee
                        DigitalOcean Employee badge
                        July 16, 2017

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

                        - Andrey

                          JournalDev
                          DigitalOcean Employee
                          DigitalOcean Employee badge
                          October 15, 2017

                          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

                            JournalDev
                            DigitalOcean Employee
                            DigitalOcean Employee badge
                            March 5, 2019

                            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

                              JournalDev
                              DigitalOcean Employee
                              DigitalOcean Employee badge
                              January 13, 2020

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

                              - kranthi

                                JournalDev
                                DigitalOcean Employee
                                DigitalOcean Employee badge
                                January 12, 2021

                                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

                                  Try DigitalOcean for free

                                  Click below to sign up and get $200 of credit to try our products over 60 days!

                                  Sign up

                                  Join the Tech Talk
                                  Success! Thank you! Please check your email for further details.

                                  Please complete your information!

                                  Become a contributor for community

                                  Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                                  DigitalOcean Documentation

                                  Full documentation for every DigitalOcean product.

                                  Resources for startups and SMBs

                                  The Wave has everything you need to know about building a business, from raising funding to marketing your product.

                                  Get our newsletter

                                  Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

                                  New accounts only. By submitting your email you agree to our Privacy Policy

                                  The developer cloud

                                  Scale up as you grow — whether you're running one virtual machine or ten thousand.

                                  Get started for free

                                  Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

                                  *This promotional offer applies to new accounts only.