Tutorial

Java ThreadLocal Example

Published on August 3, 2022
Default avatar

By Pankaj

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

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

Learn more about us


About the authors
Default avatar
Pankaj

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
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

    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
      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
        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
          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
            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 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
                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
                  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
                    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

                      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!

                      Get our biweekly newsletter

                      Sign up for Infrastructure as a Newsletter.

                      Hollie's Hub for Good

                      Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

                      Become a contributor

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

                      Welcome to the developer cloud

                      DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

                      Learn more
                      DigitalOcean Cloud Control Panel