Thursday, September 29, 2011

ThreadLocal

"You need to change method-signature and pass a variable from method-A to method-B to method-C and then print it. Who wants to change those many classes on a short-notice? And still there is a possibility of intermingled output with multiple-threads," a friend uttered in exasperation. We thought to explore a way of implementing what he needed(pass a new parameter) without actually changing the method-signatures, thereby not affecting other code. And also, see if we could somehow make that passed value thread-safe.

ThreadLocal came to mind. The concept of ThreadLocal is a bit elusive so I decided to put-together this blog-post with a simplest and shortest possible example. In simplest terms, ThreadLocals could be used to associate a state to a thread-of-execution, where the normal variables can not work. And we could use that thread-state to attach the parameter we want to pass, and down the thread-of-execution it could be retrieved by other code. Problem solved:  no method-signature changes, and thread-safe.

Here from javadoc about the class java.lang.ThreadLocal<T>:

This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has 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).


To keep the example simple, we will start only two named threads, and will attempt to retain thread-name in a variable as a state during a thread-of-execution. And to compare/contrast our attempts, we will store the thread-name in a ThreadLocal variable, and also in a normal variable.

Here is the execution output of the above code:

Fred#State1=>Fred#State2=>Fred
Lucy#State1=>Lucy#State2=>Lucy
Fred#State1=>Lucy#State2=>Fred
Lucy#State1=>Lucy#State2=>Lucy
Fred#State1=>Lucy#State2=>Fred
Lucy#State1=>Lucy#State2=>Lucy
Fred#State1=>Lucy#State2=>Fred

As you could see, the State1, retained in a normal variable was overwritten by the last thread as it entered the Running state. It could even have been "Fred", if that thread was to enter the Running state towards the end. So clearly, using a normal variable as above to retain state in a thread-of-execution doesn't work. Now contrast that too State2 and see how each thread-of-execution correctly prints the assigned state.

So next time when you are debugging a piece of code with multiple-threads, try using it. An example use-case would be in servlets as  each request creates a new thread-of-execution, and the servlet in-turn calls business-methods. You may be able to add request-specific, thread-specific data in the servlet and be able to access it deep-down in other methods where access to HttpSession or other shared-objects may not be possible.


No comments:

Post a Comment