Java ThreadLocal

Prerequisite

Java Multithreading

Please read the previous blog for detailed information.

Java.lang.ThreadLocal class in Java

This class provides thread local variables that can only be read and written by the same thread. This implies that even if two threads are executing the same code, and the code has a reference to the same ThreadLocal variable, the two threads cannot see each other’s ThreadLocal variables. Thus, the Java ThreadLocal class provides a simple way to make code thread safe that would not otherwise be so.

These variables differ from their normal counterparts in the sense that if a thread is accessing these variable via certain methods, each thread will have its own independently initialized copy of the variable. 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). 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).

Purpose of ThreadLocal in java

  • Basically it is an another way to achieve thread safety apart from writing immutable classes.
  • Since Object is no more shared there is no requirement of Synchronization which can improve scalability and performance of application.
  • It extends class Object.
  • ThreadLocal provides thread restriction which is extension of local variable. ThreadLocal are visible only in single thread. No two thread can see each others thread local variable.
  • For example, anytime you write a Java application, you are working in a multi-threaded environment. Each time a client makes a request, the application server (whether it’s Apache’s Tomcat, JBoss, Jetty, or any other) allocates a thread to respond to that client. In most cases, the application server uses a thread pool. As the name implies, the threads are pooled: the application server creates some threads when it starts, and doles them out to handle the incoming requests as needed. When the request is fulfilled, the thread is returned to the pool until it is needed again. Now, the question is, “What happens if two clients make requests at the same time?”
  • Let’s say we have a service that calculates the monthly payments on a loan based on the principal, annual interest rate, and length of the loan. If two people ask for the correct repayment installments on a loan at the same time, the parameters could get mixed, and one or both of the users would get the wrong results. One typical way to solve this problem is to use a new instance each time we need to calculate the interest, and in most cases, that is indeed the correct answer. However, sometimes creating a new instance of a class is costly, and we may want to reuse the ones we create as much as possible. So, here the role of ThreadLocal comes into play.

ThreadLocal Methods

Creating a ThreadLocal

You create a ThreadLocal instance just like you create any other Java object – via the new operator. Here is an example that shows how to create a ThreadLocal variable:

private ThreadLocal threadLocal = new ThreadLocal();

This only needs to be done once per thread. Multiple threads can now get and set values inside this ThreadLocal, and each thread will only see the value it set itself.

Set ThreadLocal Value

Once a ThreadLocal has been created you can set the value to be stored in it using its set() method.

threadLocal.set("A thread local value");

Get ThreadLocal Value

You read the value stored in a ThreadLocal using its get() method. Here is an example obtaining the value stored inside a Java ThreadLocal:

String threadLocalValue = (String) threadLocal.get();

Remove ThreadLocal Value

It is possible to remove a value set in a ThreadLocal variable. You remove a value by calling the ThreadLocal remove() method. Here is an example of removing the value set on a Java ThreadLocal:

threadLocal.remove();

Generic ThreadLocal

You can create a ThreadLocal with a generic type. Using a generic type only objects of the generic type can be set as value on the ThreadLocal. Additionally, you do not have to typecast the value returned by get(). Here is a generic ThreadLocal example:

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

Now you can only store strings in the ThreadLocal instance. Additionally, you do not need to typecast the value obtained from the ThreadLocal:

myThreadLocal.set("Hello ThreadLocal");

String threadLocalValue = myThreadLocal.get();

Initial ThreadLocal Value

If you set values on a ThreadLocal object, the values are visible to the thread that set the value. No thread can set an initial value on a ThreadLocal using set() method which is visible to all threads.

Instead you can specify an initial value for a ThreadLocal object by subclassing ThreadLocal and overriding the initialValue().

private ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {  
    @Override protected Integer initialValue()   
    {  
        return nextId.getAndIncrement();  
    }  
};  

Now all threads can see the same initial value when calling the get() method before having called set() method.

ThreadLocal Example Code 1

package com.wordpress.compilationerrors;
import java.lang.Thread;
import java.lang.Runnable;
import java.lang.*;
class ThreadLocalExp
{
public static class MyRunnable implements Runnable
{
private ThreadLocal<Integer> threadLocal =
new ThreadLocal<Integer>();
@Override
public void run() {
threadLocal.set( (int) (Math.random() * 50D) );
try
{
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.println(threadLocal.get());
}
}
public static void main(String[] args)
{
MyRunnable runnableInstance = new MyRunnable();
Thread t1 = new Thread(runnableInstance);
Thread t2 = new Thread(runnableInstance);
// this will call run() method
t1.start();
t2.start();
}
}

Running the code

The above example creates a single MyRunnable instance which is passed to two different threads. After calling the start( ) method, both the threads execute the run( ) method and sets different values on the ThreadLocal instance. If the access to the set( ) call had been synchronized and it had not been a ThreadLocal object, the second thread would have overridden the value set by the first thread.

Since, it is a ThreadLocal object so both the threads cannot see the value of each other. They can set and get different values.

ThreadLocal Example Code 2

package com.wordpress.compilationerrors;
import java.lang.Thread;
import java.lang.Runnable;
import java.lang.*;
// illustrating the use of get(), set(), and remove() ThreadLocal methods
class ThreadLocalExp {
public static void main(String[] args)
{
ThreadLocal<Number> anjaliNumber = new ThreadLocal<Number>();
ThreadLocal<String> anjaliString = new ThreadLocal<String>();
// setting the value
anjaliNumber.set(100);
// returns the current thread's value
System.out.println("value = " + anjaliNumber.get());
// setting the value
anjaliNumber.set(90);
// returns the current thread's value of
System.out.println("value = " + anjaliNumber.get());
// setting the value
anjaliNumber.set(88.45);
// returns the current thread's value of
System.out.println("value = " + anjaliNumber.get());
// setting the value
anjaliString.set("compilationErrors");
// returns the current thread's value of
System.out.println("value = " + anjaliString.get());
// removing value
anjaliString.remove();
// returns the current thread's value of
System.out.println("value = " + anjaliString.get());
// removing vale
anjaliNumber.remove();
// returns the current thread's value of
System.out.println("value = " + anjaliNumber.get());
}
}

Running the code

ThreadLocal Example Code 3

package com.wordpress.compilationerrors;
import java.lang.Thread;
import java.lang.Runnable;
import java.lang.*;
// illustrating the use of Java ThreadLocal initialValue() method
class NewThread extends Thread {
private static ThreadLocal anjali = new ThreadLocal(){
protected Object initialValue(){
return new Integer(a–);
}
};
private static int a = 15;
NewThread(String name)
{
super(name);
start();
}
public void run()
{
for (int i = 0; i < 2; i++)
System.out.println(getName() + " " + anjali.get());
}
}
public class ThreadLocalExp {
public static void main(String[] args)
{
NewThread t1 = new NewThread("compilationErrors1");
NewThread t2 = new NewThread("compilationErrors2");
}
}

Running the code

Feel free to post queries.

Leave a comment

Design a site like this with WordPress.com
Get started