Pages

Monday, July 14, 2014

Helping methods indentify their calling threads with ThreadLocal class

In multi threaded applications in occasions we want to identify the thread that called certain method.
We could pass some additional parameter for that purpose to the method we are calling, but that wouldn't be very elegant.
The class ThreadLocal allows us to manage an object within the current Thread scope.

Let's have a look at an example...

The class below called sample Thread, uses some service and that service has interest in knowing who called it.
So What we do is create some context with come kind of unique identifier(e.g ThreadName,UUID...) and then we give that context to the class ThreadLocal to handle it(We will create an special wrapper class to hold ThreadLocal).

 public class SampleThread extends Thread {  
   @Override  
   public void run() {  
     ThreadContext threadContext = new ThreadContext();  
     threadContext.setId(getName());  
     ContextManager.set(threadContext);  
     new BussinessService().bussinessMethod();  
     ContextManager.unset();  
   }  
 }  

The context could be anything we want, but in this example I will be using the Thread name.

 public class ThreadContext {  
   private String id = null;  
   public String getId() {  
     return id;  
   }  
   public void setId(String id) {  
     this.id = id;  
   }  
 }  

The class ContextManager will act as a container that will allow us to access and modify the context of the Thread.


 public class ContextManager {  
   public static final ThreadLocal threadLocal = new ThreadLocal();  
   public static void set(ThreadContext context) {  
     threadLocal.set(context);  
   }  
   public static void unset() {  
     threadLocal.remove();  
   }  
   public static ThreadContext get() {  
     return (ThreadContext) threadLocal.get();  
   }  
 }  

With this infrastructure in place, the Service can identify the calling thread.

 public class BussinessService {  
     public void bussinessMethod() {  
       ThreadContext threadContext = ContextManager.get();  
       System.out.println(threadContext.getId());  
     }  
 }  

Finally just to demo the concept we could just create a couple of Threads and run them to see how they are identified by the services via their context.

 public class Main {  
   public static void main(String args[]) {  
     SampleThread threadOne = new SampleThread();  
     threadOne.start();  
     SampleThread threadTwo = new SampleThread();  
     threadTwo.start();  
   }  
 }  

Share with your friends