ThreadLocal in multithreading in java - methods and usage with program


This question will test your command in multi threading, can you really create some perfect multithreading application or not. ThreadLocal is a class which provides thread-local variables.

What is ThreadLocal ?
ThreadLocal is a class which provides thread-local variables. Every thread has its own ThreadLocal value that makes ThreadLocal value threadsafe as well.


For how long Thread holds ThreadLocal value?
Thread holds ThreadLocal value till it hasn’t entered dead state.

Can one thread see other thread’s ThreadLocal value?
No, thread can see only it’s ThreadLocal value.

Are ThreadLocal variables thread safe. Why?
Yes, ThreadLocal variables are thread safe. As every thread has its own ThreadLocal value and one thread can’t see other threads ThreadLocal value.

Application of ThreadLocal?
  1. ThreadLocal are used by many web frameworks for maintaining some context (may be session or request) related value.
    • In any single threaded application, same thread is assigned for every request made to same action, so ThreadLocal values will be available in next request as well.
    • In multi threaded application, different thread is assigned for every request made to same action, so ThreadLocal values will be different for every request.

  1. When threads have started at different time they might like to store time at which they have started. So, thread’s start time can be stored in ThreadLocal.


Creating ThreadLocal >

private ThreadLocal<String> threadLocal =   new ThreadLocal<String>();

We will create instance of ThreadLocal. ThreadLocal is a generic class, i will be using String to demonstrate threadLocal.
All threads will see same instance of ThreadLocal, but a thread will be able to see value which was set by it only.

How thread set value of ThreadLocal >

threadLocal.set( new Date().toString());

Thread set value of ThreadLocal by calling set(“”) method on threadLocal.


How thread get value of ThreadLocal >

threadLocal.get()

Thread get value of ThreadLocal by calling get() method on threadLocal.



How thread remove value of ThreadLocal >

threadLocal.remove();

Thread can remove value of ThreadLocal by calling remove() method on threadLocal.
Once value has been removed get() method will return null.


Full Program on how to use ThreadLocal >
import java.util.Date;
public class ThreadLocalUsage {
   public static class MyRunnable implements Runnable {
       private ThreadLocal<String> threadLocal =   new ThreadLocal<String>();
      
       @Override
       public void run() {
         
          threadLocal.set(new Date().toString());
         
          try {
                       Thread.sleep(4000);
                 } catch (InterruptedException e) { e.printStackTrace();    }
         
        System.out.println(Thread.currentThread().getName()+
             " start time = "+threadLocal.get());
       }
   }
   public static void main(String[] args) throws InterruptedException {
       MyRunnable myRunnable = new MyRunnable();
       Thread thread1 = new Thread(myRunnable,"Thread-1");
       Thread thread2 = new Thread(myRunnable,"Thread-2");
       thread1.start();
       Thread.sleep(1000); //Start thread-2 after 1 second.
       thread2.start();
   }
}

/*OUTPUT
Thread-1 start time = Sun Mar 08 4:08:43 IST 2015
Thread-2 start time = Sun Mar 08 4:08:44 IST 2015
*/

In the program, Thread-1 started and after 1 second Thread-2 also started.
Thread-1 called threadLocal.set(new Date().toString())  and set the threadLocal value i.e. value when thread was started and then went for sleep.
Than, Thread-2 called threadLocal.set(new Date().toString())  and set the threadLocal value i.e. value when thread was started and then went for sleep.
When both the threads waked up they called threadLocal.get() and we saw that both threads were having different threadLocal value i.e. time at which they started.
Conclusion : Thread-1 and Thread-2 were having different threadLocal value.

Was either of threads able to see each others threadLocal value?
No, neither of thread was not able to see each other value, as threadLocal value printed by both threads was different.


Setting up ThreadLocal initial value >
By overriding initialValue() method of ThreadLocal we can set initial value of ThreadLocal.
import java.util.Date;
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class ThreadLocalInitialValue {
   public static class MyRunnable implements Runnable {
       private ThreadLocal<String> threadLocal =   new ThreadLocal<String>(){
          @Override
          protected String initialValue() {
             return (new Date().toString());
        }
       };
      
       @Override
       public void run() {
        System.out.println(Thread.currentThread().getName()+
                        " start time = "+threadLocal.get());
       }
   }
   public static void main(String[] args) throws InterruptedException {
       MyRunnable myRunnable = new MyRunnable();
       Thread thread1 = new Thread(myRunnable,"Thread-1");
       thread1.start();
   }
}
/*OUTPUT
Thread-1 start time = Sun Mar 08 4:25:20 IST 2015
*/


What will happen if ThreadLocal was replaced with some other object in above program>
If ThreadLocal is replaced with some other object let’s say String than both the threads will hold same value for threadLocal.

private ThreadLocal<String> threadLocal =   new ThreadLocal<String>();

Replace ThreadLocal with String.

private String threadLocal = "";


import java.util.Date;
/** Copyright (c), AnkitMittal JavaMadeSoEasy.com */
public class ThreadLocalReplaceWithString {
   public static class MyRunnable implements Runnable {
       private String threadLocal = new String("");
      
       @Override
       public void run() {
         
          threadLocal= new Date().toString();     
         
          try {
                       Thread.sleep(4000);
                 } catch (InterruptedException e) { e.printStackTrace(); }
       
          System.out.println(Thread.currentThread().getName()+
                              " start time = "+threadLocal);
       }
   }
   public static void main(String[] args) throws InterruptedException {
       MyRunnable myRunnable = new MyRunnable();
       Thread thread1 = new Thread(myRunnable,"Thread-1");
       Thread thread2 = new Thread(myRunnable,"Thread-2");
       thread1.start();
       Thread.sleep(1000); //Start thread-2 after 1 second.
       thread2.start();
      
   }
}
/*OUTPUT
Thread-1's start time = Sun Mar 08 4:33:00 IST 2015
Thread-2's start time = Sun Mar 08 4:33:00 IST 2015
*/
ThreadLocal was replaced with String.
Thread-1’s threadLocal value was overridden by Thread-2’s threadLocal value. So, threadLocal printed same start time for both threads.




RELATED LINKS>

Thread Pool, Thread local, Busy Spin >

Implement Thread pool in java

ThreadLocal in multithreading in java - methods and usage with program

Busy Spin - What is busy spin? Consumer Producer problem with busy spin and solution to busy spin.



Situation based questions -

Suppose you have 2 threads (Thread-1 and Thread-2) on same object. Thread-1 is in synchronized method1(), can Thread-2 enter synchronized method2() at same time?


No comments:

Post a Comment