Its bottom layer is implemented using a THREADLOCALMAP (each thread has this object), the entry key name is an instance of the threadlocal of an object, the key value is a specific value, a thread can bind multiple Threadlocal objects ; Also, the thread object's member Threadlocalmap is lazy-loaded and is loaded only when it is used: (Note: Threadlocals Here is an instance of a member variable threadlocalmap of thread T)/** * Create The map associated with a ThreadLocal. Overridden in * inheritablethreadlocal. * @param t The current thread @param firstvalue value for the initial entry of the map * /void createmap (Thread T, T firstvalue) {new Threadlocalmap (this, firstvalue); }
Here is the key name for entry using an instance of the Threadlocal object
/** * Construct a new map initially Containi Ng (Firstkey, Firstvalue). * Threadlocalmaps is constructed lazily, so we had create * one when we had at least one entry to put in it. */ Threadlocalmap (ThreadLocal <?> Firstkey, Object firstvalue) {table = new entry[initial_capacity]; int i = firstkey.threadlocalhashcode & (Initial_capacity-1 = new Entry (Firstkey, Firstvalue) ; Size = 1; Setthreshold (initial_capacity); }
Here is the source of the set method, using the Open address method
/*** Set The value associated with key. * * @paramkey The Thread local object *@paramvalue The value to is set*/ Private voidSet (threadlocal<?>key, Object value) { //We don ' t use a fast path as with get () because it 's at//least as common to use Set () to create new entries as//it is-to-replace existing ones, in which case, a fast//path would fail more often than not.entry[] Tab=table; intLen =tab.length; inti = Key.threadlocalhashcode & (len-1); for(Entry e =Tab[i]; E!=NULL; E= Tab[i =Nextindex (i, Len)]) {ThreadLocal<?> k =E.get (); if(k = =key) {E.value=value; return; } if(k = =NULL) {replacestaleentry (key, value, I); return; }} Tab[i]=NewEntry (key, value); intSZ = + +size; if(!cleansomeslots (i, SZ) && sz >=threshold) rehash (); }
2. Possible problems: Memory leaks Note: Because ThreadLocal.ThreadLocalMap.Entry inherits from a weak connection, the next GC can release the memory of the key name Threadlocal object when the strong connection is broken. However, value: Strong connection used in ThreadLocal.ThreadLocalMap.Entry, cannot be automatically gc by program, must trigger GC through remove, set, GET, etc./*** The entries in this hash map extend WeakReference, using * It 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 is expunged from table. Such entries is referred to * as "stale entries" in the code that follows. */ Static classEntryextendsWeakreference<threadlocal<?>> { /**The value associated with this ThreadLocal.*/Object value; Entry (ThreadLocal<?>K, Object v) { Super(k); Value=v; } }
PS: The first time to write a blog, write is only some of their own experience, there are any shortcomings welcome to point out