Using Thread Local Variables

   

Using Thread Local Variables

The ThreadLocal and InheritableThreadLocal are two classes that most Java developers might not use properly or even know exist. These classes provide a mechanism to set up an object that can be associated with a specific thread and have the thread access its copy of the object. In other words, it's a way to associate a state with a thread. The ThreadLocal class can hold onto objects only, not primitives.

You might be asking, how is this different than declaring a private variable within a thread class. That's an important question. Normally, a ThreadLocal object is declared as a private static variable in some class. You'll remember that this means all instances of this class have access to it. Every time a new thread accesses this object by using the getter or setter, the thread is accessing its copy of the object. The first time a thread uses the get or set method on a ThreadLocal instance, a new copy of the object is associated with that particular thread. From that point on, the thread will access its own copy of the object and not any other instance that belongs to other threads in the system. You can kind of think of this as a hash table in which the key is the thread and the value is the object that is associated with just that thread.

The good news is most of the maintenance is handled by the ThreadLocal implementation itself. All the developer has to do is create a single static instance of the ThreadLocal object, optionally assigning an initial value for the object, and then any thread that accesses the static ThreadLocal object gets an implicit reference to its copy of the object. The initialValue method is called one time per thread. The initial Value method in the ThreadLocal class initializes the object that the ThreadLocal instance holds onto to a null value. If there is a need for an initial value other than null, the ThreadLocal class must be overridden. The thread holds onto its reference of the ThreadLocal object as long as the thread is alive and the ThreadLocal object is accessible.

The use of this still might be confusing, so take a look at a simple example to see how to use this class. Listing 11.7 shows a class that extends the ThreadLocal class as an inner class inside a new Thread class.

Listing 11.7 Source Code for ThreadLocalExample.java
 public class ThreadLocalExample extends Thread {   // Static instance for all threads to use   private static MyThreadLocal threadLocal = new MyThreadLocal(); // Holds which thread number this instance is. Used for display only   private int threadCount = 0;   // Default Constructor   public ThreadLocalExample( String threadName, int threadCount )   {     super( threadName );     this.threadCount = threadCount;   }   // Use an inner class to declare your new class   static private class MyThreadLocal extends ThreadLocal   {     // If this is the first time the get or set is used,     // this method will be called automatically     protected Object initialValue()     {       // Initialize a new Double object       return new Double (Math.random() * 1000.0);     }   }   // Override the parent's run method   public void run()   {     // Print out the initial value for the ThreadLocal Object     System.out.println( getName() + " - Initial Value: " + this.threadLocal.get() ); // Change the value for this thread only     this.threadLocal.set( new Integer( threadCount ) ); // Print out the value, so you can be sure that only your instance changed     System.out.println( getName() + " - Current Value: " + this.threadLocal.get() );   } } 

Listing 11.8 shows a class called ThreadLocalMain that can be used to test the ThreadLocalExample class.

Listing 11.8 Source Code for ThreadLocalMain.java
 public class ThreadLocalMain {   public ThreadLocalMain()   {   }   public static void main(String[] args)   {     ThreadLocalExample ex1 = new ThreadLocalExample( "Thread 1", 1 );     ThreadLocalExample ex2 = new ThreadLocalExample( "Thread 2", 2 );     ex1.start();     ex2.start();   } } 

Running the ThreadLocalMain class from Listing 11.8, here's the output:

 C:\jdk1.3se_book\classes>java ThreadLocalMain Thread 1 - Initial Value: 412.2123189553676 Thread 1 - Current Value: 1 Thread 2 - Initial Value: 51.71279074374135 Thread 2 - Current Value: 2 C:\jdk1.3se_book\classes> 

Notice that when the value for thread 1 was changed, it did not modify the value for thread 2. Only when the value for thread 2 was actually changed, did it in fact change. The ThreadLocal object does maintain a copy of the object for each thread.

The InheritableThreadLocal class subclasses the ThreadLocal class and provides a way for a parent thread to pass along the initial value of the ThreadLocal object to any child threads that are created from the parent thread. By default, the child thread gets a copy of the ThreadLocal object that is equal to the parent's value. It's not the same reference, but a clone of the actual value. If the child's copy of the ThreadLocal object needs to modify the initial value that was passed down from the parent, it can override the method childValue on the InheritableThreadLocal class and do whatever needs to be done on the initial value. The InheritableThreadLocal is preferred over the ThreadLocal class when the per-thread object must be passed from the parent thread to any child threads created.

   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net