Before reading this document further, please note that it, and any code snippets it lists, are distributed under BSD license If you disagree to any of the terms of the license, please close this page now.

What is ThreadLocal

ThreadLocal class in Java Development Kit (JDK) allows programmers to create thread bound variables, that are managed by the JDK itself. An instance of a thread local variable is created in an object that is shared between the threads, but using get or set operation on that instance from within any thread will operate with a container that is dedicated to that thread only.

The fact that you can only retreive or modify the value of a thread local variable from a current thread is actually a shortcoming. There is absolutely nothing that prevents a user from specifying the thread, that should be used to retrieve or mofify the value, but current implementation of ThreadLocal is locked into operating with value of Thread.currentThread(), so the visibility into thread local is limited to the thread you are currently running. Certainly, if the API allowed to specify the actual thread, it would be necessary to synchronize the access, at least for writing, but this could have been documented, and it would become users responsibility to do such synchronization. Currently, there is no synchronization involved when using thread local variables, as it is always guaranteed that you are working with the thread object instance that you are currently running in.

Note, that though thread locals are supported since JDK 1.2, prior to JDK 1.4 they were poorly implemented, and introduced a lot of contention when accessed from multiple threads, severely slowing down the system.

Why the ThreadLocal

ThreadLocal is a convinience tool for creating individual thread variables. Most of the native threading libraries support this kind of functionality by giving the developers API to set/get attributes of a given thread object, or just simply giving them a single address field within the thread context variable, that they can then point to any block of memory, in which case every thread can have it's own pointer to a data structure that the developer wants to be thread specific.

However, these other threading libraries do usually provide a way to iterate over all existing threads, so one can get access to all the contexts, and therefore to all the attributes, or externally specified data structures, but using JDK that won't be possible. You can get an iterator over all your threads, but you can't get access to all the thread local variables of a given thread, or even to a specific thread local variable (i.e. if this chunk of code could obtain a reference to an instance of a ThreadLocal class that denoted that variable).

The ThreadLocal is still a useful instrument available to Java developer. The usual alternative way to achieve the same would be to create a table of sorts, that would map thread objects to specific object instances. For example, declaring a shared hash map, with keys being threads instances, and values being references to objects. This table needs to be specially maintain to remove any entries that are obsolete because a thread has stopped. Such maintenance imposes a signgicant overhead, or creation of an utility class. One way to automatically clean up table entries would be to define them as weak references. You would still need to regularly iterate over the elements of that table and remover the elements whose references became unreachable.

Other methods

ThreadLocal uses special functions of JDK that are not available to regular developers. Since every thread in Java is uniquely represented by an instance of a Thread class, the one unique thing for a thread is such an instance. JDK implementation assigns a special variable to every thread instance, called threadlocals, its type is ThreadLocal.ThreadLocalMap. That variable is not accessible to a JDK developer directly. To have a place for your thread local variables, you either need to have a write access to some field in the Thread instance, or you will have to somehow index your variables by an instance of a thread object. Since JDK doesn't give you access to threadlocals (And it only exists since JDK 1.2), and there is no other container that you can use to stash your objects into. Let's look over other methods of accessing thread variables.

Extending thread class

If you are writing an application where you have complete control of the threads you instantiate, or if any of the thread local variables you are using would only belong to the threads you spawn, the best approach would be to extend the Thread class, and assign the variables directly into the derived class:

public class MyThread extends Thread {
    
    public String myLocalVar0;
    public int myLocalVar1;
    // ...

    public void run() {
        // my thread code
    }

    // ....

    // access the variable
    MyThread t = (MyThread)Thread.currentThread();
    System.out.println(t.myLocalVar0);
    // set the variable
    t.myLocalVar1 ++;

}
If you can pull this off, this would be the fastest way for you to get access to thread specific variables. Fastest by execution time that is.

Joining all thread local variables

While using thread local variables does allow you to avoid finding them using a thread index, there is still a search operation performed inside the map of all the variables declared for a thread. The way JDK finds your variable when you request for it from a ThreadLocal instance, is it retrieves the map of variables form the Thread instance, and then uses the ThreadLocal instance as a key into that map to retrieve the actual object. Every time you call get() or set(), this lookup has to happen. It is true, that JDK does attempt to do a good effort in indexing the tread locals, the thread local map is custom made, and thread locals have a custom hash value, that expedites the lookups.

I am not really that good with reverse engineering the algorithms, but the general idea behind thread local lookups is as follows. The table is represented as an array, with initial size of 16. When the array needs to be extended, its size is always doubled. When keys are looked up, the initial index that is used to look up a key is hash & (size - 1) Every thread variable is assigned a predefined hash value, off of a certain counter. The counter is initialized with value of 0x61C88647, every next hash value is one more increment of that value. When the table is extended, the table is rebuilt, so hash & (size - 1) is always used as an initial key. If when writing or reading, the key doesn't match the entry in the table, the code loops forward the array, reverting to the beginning at the end of the array. I assume the creators picked that magical number mentioned above because if you keep adding this number, the bits at the end of the result provide enough dispersion across all combination to minimize the amount of lookups. In fact, as I tested it through to the array length of 2097152, and every time it took only one lookup operation. There is more extensive discussion on the significance of this number at http://www.javaspecialists.eu/archive/Issue164.html

To avoid having any look up logic when a thread local variable is being looked up, you can join all of your thread local varaibles into a single ThreadLocal instance, and then retrieving your variables from that index:

public class MyThreadLocal extends ThreadLocal<Container> {
    
    protected Container initialValue() {
        return new Container();
    }

}
//...
public class Contianer {
    
    public String myLocalVar0;
    public int myLocalVar1;

}
//...
// Then declare the local variable

MyThreadLocal tl = new MyThreadLocal();

// instead of creating individual variables
// ThreadLocal<String> myLocalVar0 
// ThreadLocal<Integer> myLocalVar1;

In this case you would only need to have one thread local variable, which will then reference all of your variables. This also allows you to store the primitive types.

Storing the variables in a map

If you for some reason can not use ThreadLocal variables, you can store variables directly in a map. Say, you can use an instance of java.util.Hashtable, or some implementation of java.util.Map map. In either case, you would have to use the instance of Thread object as the key, and some value as the value. You can use the same "joining" method described for thread local variables in this case.

There are a few potential problems with this solution. Any hash map depends on a "good" hash value, since thread class doesn't implement a custom hashCode, and its equals() method is inhereted from java.lang.Object, this is ineffective, every lookup can effectively result into a long iteration over an internal array or list of hash table. So, it would be better if we could use a sequential thread value that never changes, and is predictable and easily comparable. So then we can use a sorted map, since it's foreseeable that the table will be read and written to way more frequent than the structure of the table will be modified. Note, that reliable threads IDs seem to only be available since JDK 1.5.

The next problem to watch out is synchronization. If your variable is being requested and changed from multiple threads, your map will have to be synchronized for access. You can choose a synchronized map from the beginning, or a Hashtable that is always synchronized, but, as you have more and more keys in the table, the lookups will become very slow, effectively creating a bottleneck on the variable retrieval. The best way to synchronize such access is to use independent read/write lock (which is only available to you since JDK 1.5).

The very last problem is clean up. You will need to somewhat regularly clean up the map from the variables whose threads have exited. If you, for some reason, need to preserve these variables for longer times, you will have to figure out the policy that suits you better. In the example below we will use the thread's terminated status. Thread local use WeakReference objects, that point to thread objects, so if threads die, the reference nulls out, and that at some point indicates that the thread variable can be released. Thread local implementation cleans up nulled references if variable is being replaced, or when table of variables needs to be expanded (so may be it doesn't need to be expanded after the clean up).

So, let's come up with a sample code that shows how the thread local variables can be stored in a map. The implentation assumes JDK 1.5, and also assumes that you join all of your variables together in a single container class. The sample is a utility class that provides service to retrieve / store the container for your local variables. Download the sample code. I haven't so far done any testing on this code, so let me know if you find things wrong with it.

One of the key elements of effectively accessing the variables is to use mutable classes, and change the values of the classes instead of re-assigning the variable itself. For example:


BAD:

ThreadVarStore<Integer> localVar =
    new ThreadVarStore<Integer>(null);

// ....
localVar.set(0);
// ....
int varNow = localVar.get();
varNow += 12;
localVar.set(varNow);

GOOD:

class MyContainer {
    int value;
    // also define other variables here
}

ThreadVarStore<MyContainer> localVar =
    new ThreadVarStore<MyContainer>(MyContainer.class);

// ....
MyContainer varNow = localVar.get(localVar);
varNow.value += 12;
//

Conclusion

So let's review the most effective ways of using thread variables. I will list them in order of performance, first listed are the best performing ones.

  1. Extending the thread class
    Extend the thread class and store your thread variables inside the extended class as instance variables. An access will cost you an optional call to Thread.currentThread() method, and a field access, which will be optimized by JIT.
  2. Joining the variables
    Use the ThreadLocal class, but only create a single thread local variable, and store a mutable class where you read and write the varaibles. An access will cost you a call to Thread.currentThread() method, then a lookup inside the thread local table (very fast if you have very few thread locals), and then a field access (optimized by JIT). Note, that it is always best to use mutable classes for storing data into thread locals, since then changing the value will amount to updating a field, rather than replacing an entry in the thread local table (or your internal table).
  3. Using external map Using external map or table would be the slowest way, and your table needs to be designed correctly in this case. This is the only method that allows you general access to the variables in all the threads there are, though. An example is like one storage sample class referenced above.

That's it !
by Pawel S. Veselov, 2008
[Back] [Or press "BACK" button on your cool browser ;)]
This page was accessed
 times.
Traffic load: