ThreadLocal can define a variable within a thread, the variable is within the thread, so it is thread-safe.
(This class provides thread-local variables. These variables differ from * their normal counterparts in that each thread that accesses one (via its* <tt>get</tt> or <tt>set</tt> method) has its own, independently initialized
* copy of the variable.)
How to use the ThreadLocal class:
public class ThreadLocalTest { public class ThreadLocalVariableHolder { private static ThreadLocal<Integer> value = new ThreadLocal<Integer>(){ private Random rand = new Random(47); //Override the initialValue method of the parent class to initialize the variables in the thread @Override protected Integer initialValue() { return rand.nextInt(10000); } }; public static void increment(){ value.set(value.get() + 1); } public static int get(){ return value.get(); } }
ThreadLocal class implementation principle:
The ThreadLocal class implements the principle of threading, and each thread has a ThreadLocalMap to store all the ThreadLocal variables of the thread.
Thread: /* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null;
The key of ThreadLocalMap is ThreadLocal, and the value is the variable of thread storage corresponding to ThreadLocal. Note here that Entry is a WeakReference, so that HashMap will not overflow.
/** * The entries in this hash map extend WeakReference, using * its main ref field as the key (which is always a * ThreadLocal object). Note that null keys (i.e. entry.get() * == null) mean that the key is no longer referenced, so the * entry can be expunged from table. Such entries are referred to * as "stale entries" in the code that follows. */ static class Entry extends WeakReference<ThreadLocal> { /** The value associated with this ThreadLocal. */ Object value; Entry(ThreadLocal k, Object v) { super(k); value = v; } }
ThreadLocal's get method
/** * Returns the value in the current thread's copy of this * thread-local variable. If the variable has no value for the * current thread, it is first initialized to the value returned * by an invocation of the {@link #initialValue} method. * * @return the current thread's value of this thread-local */ public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t);//Get the ThreadLocalMap in the thread if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) return (T)e.value; } return setInitialValue(); }