Sunday 14 May 2017

Java ThreadLocal


The ThreadLocal class in Java enables us to create variables that can only be read and written by the same thread. Thus, even if two threads are executing the same code, and the code has a reference to a ThreadLocal variable, then the two threads cannot see each other's ThreadLocal variables.

ThreadLocal is another way to achieve thread-safety apart from writing immutable classes. As multi-threaded or concurrent code have the very huge cost of synchronization or locking which can greatly affect Scalability of application, however, there is no choice other than synchronizing if we are sharing objects between multiple threads.

ThreadLocal is a different way to achieve thread-safety, it doesn't address synchronization requirement, and instead, it eliminates sharing by providing explicitly copy of Object to each thread. Since Object is no more shared there is no requirement of Synchronization which can improve scalability and performance of the application.

Usage of ThreadLocal
1) ThreadLocal is fantastic to implement Per Thread Singleton classes or per thread context information like transaction id.

2) We can wrap any non-Thread Safe object in ThreadLocal and suddenly its uses become Thread-safe, as its only being used by Thread Safe.

Example: ThreadLocal is sharing SimpleDateForamt. Since SimpleDateFormat is not thread-safe, having a global formatter may not work but having per Thread formatter will certainly work.

3) ThreadLocal provides another way to extend Thread. If you want to preserve or carry information from one method call to another you can carry it by using ThreadLocal. This can provide immense flexibility as you don't need to modify any method. (This concept is used in Application server to avoid the propagation of request data).

On basic level ThreadLocal provides Thread Confinement which is an extension of a local variable. While local variable only accessible on the block they are declared, ThreadLocal are visible only in Single Thread. No two threads can see each other’s ThreadLocal variable.

Best example(ThreadLocal use in the Application Servers)
ThreadLocal is in J2EE application servers which use java ThreadLocal variable to keep track of transaction and security Context. It makes a lot of sense to share heavy object like Database Connection as ThreadLocal in order to avoid excessive creation and cost of locking in case of sharing global instance.

Points to be remember
1. ThreadLocal in Java is introduced on JDK 1.2 but it later generified in JDK 1.4 to introduce type safety on ThreadLocal variable.

2. ThreadLocal can be associated with Thread scope, all the code which is executed by Thread has access to ThreadLocal variables but two threads cannot see each other’s ThreadLocal variable.

3. Each thread holds an exclusive copy of ThreadLocal variable which becomes eligible to Garbage collection after thread finished or died, normally or due to any Exception, given those ThreadLocal variable doesn't have any other live references.

4. ThreadLocal variables in Java are generally private static fields in Classes and maintain its state inside Thread.

Note
Think twice about ThreadLocal variable while designing concurrency in the application. Don't misunderstand that ThreadLocal is alternative of Synchronization, it all depends upon the design. If the design allows each thread to have their own copy of object than ThreadLocal is there to use.

Context.java
package com.threadlocal;

public class Context {
    
     private String transactionId;

     public String getTransactionId() {
           return transactionId;
     }

     public void setTransactionId(String transactionId) {
           this.transactionId = transactionId;
     }

}

MyThreadLocal.java
package com.threadlocal;
public class MyThreadLocal {
    
     public static final ThreadLocal<Context> userThreadLocal = new ThreadLocal<Context>();

     public static void set(Context user) {
           userThreadLocal.set(user);
     }

     public static void unset() {
           userThreadLocal.remove();
     }

     public static Context get() {
           return userThreadLocal.get();
     }
}

BusinessService.java
package com.threadlocal;

public class BusinessService {

     public void businessMethod() {
          
           // get the context from thread local
           Context context = MyThreadLocal.get();
          
           System.out.println(context.getTransactionId());
     }
    
}

ThreadLocalDemo.java
package com.threadlocal;
public class ThreadLocalDemo extends Thread {

     public static void main(String args[]) {

           Thread threadOne = new ThreadLocalDemo();
           threadOne.start();

           Thread threadTwo = new ThreadLocalDemo();
           threadTwo.start();
     }

     @Override
     public void run() {
           // sample code to simulate transaction id
           Context context = new Context();
           context.setTransactionId(getName()+" Id");

           // set the context object in thread local to access it somewhere else
           MyThreadLocal.set(context);

           /* note that we are not explicitly passing the transaction id */
           new BusinessService().businessMethod();
          
           MyThreadLocal.unset();

     }
}

When to use Thread Local?
We need to understand the use case where ThreadLocal is needed.
Use Case: Consider you have a Servlet which calls some business methods and you have a requirement to generate a unique transaction id for each and every request this Servlet process and you need to pass this transaction id to the business methods, for logging purpose.

One solution would be passing this transaction id as a parameter to all the business methods. But this is not a good solution as the code is redundant and unnecessary.

To solve that, we can use Thread Local. We can generate a transaction id (either in a 
Servlet or better in a filter) and set it in the Thread Local. After this, whatever the business method, that this Servlet calls, can access the transaction id from the thread local.

This Servlet might be servicing more than one request at a time. Since each request is processed in the separate thread, the transaction id will be unique to each thread (local) and will be accessible from all over the thread’s execution (global).


No comments:

Post a Comment

Related Posts Plugin for WordPress, Blogger...