This article is organized by Colodoo (paper umbrella)
Refer to source code: jdk1.8.0_131
I’m sure a lot of people were taken aback by ThreanLocal, because I was like that at first, and it wasn’t until I was asked about it in an interview that I first heard about ThreanLocal.
Here are some concluding introductions that should be sufficient for the interview question:
- ThreadLocal is a thread-local storage mechanism provided in Java that can be used to cache data inside a thread that can retrieve cached data at any time and in any method
- The underlying ThreadLocal is implemented using a ThreadLocalMap. Each Thread object (not a ThreadLocal object) has a ThreadLocalMap. The key of the Map is a ThreadLocal object. The value of the Map is the value to be cached
- Using a ThreadLocal in a thread pool will cause a memory leak, because when a ThreadLocal is used up, it should be recycled as a key, value, and Entry object, but the thread in the pool is not recycled. Thread objects point to ThreadLocalMap by strong reference, and ThreadLocalMap points to Entry objects by strong reference. Threads are not recycled, so Entry objects are not recycled. The solution is that after using ThreadLocal objects, Manually call ThreadLocal’s remove method, and manually clear the Entry object
- The classic use of ThreadLocal is connection management (a thread holds a connection, the connection object can be passed between methods, and threads do not share the same connection).
Then explain the conclusions from the source point of view.
set
java.lang.ThreadLocal#set
Public void set(T value) {// Get Thread T = Thread.currentThread(); ThreadLocalMap = getMap(t); threadLocalMap = threadLocalMap; // Set the value if (map! = null) map.set(this, value); Else // CreateMap (t, value); }
- Get the current thread
- Gets the local storage object in the current thread
- Sets the value to the local storage object of the current thread
The ThreadLocal scope is the currentThread (currentThread), and the threads are isolated from each other.
set
java.lang.ThreadLocal.ThreadLocalMap#set
private void set(ThreadLocal<? > key, Object value) {TAB Entry[] TAB = table; Int len = tab.length; int len = tab.length; Int I = 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; } new Entry(key, value) = new Entry(key, value); int sz = ++size; if (! cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }
getMap
java.lang.ThreadLocal#getMap
ThreadLocalMap getMap(Thread t) {// get ThreadLocalMap in the Thread return t.htReadLocals; }
createMap
java.lang.ThreadLocal#createMap
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocalMap
java.lang.ThreadLocal.ThreadLocalMap#ThreadLocalMap(java.lang.ThreadLocal<? >, java.lang.Object)
ThreadLocalMap(ThreadLocal<? > firstKey, Object firstValue) {table = new Entry[INITIAL_CAPACITY]; / / calculate the subscript int I = firstKey. ThreadLocalHashCode & (INITIAL_CAPACITY - 1); Table [I] = new Entry(firstKey, firstValue); // Set size =1; // Set threshold (INITIAL_CAPACITY); }
get
java.lang.ThreadLocal#get
Public T get() {public T get() {public T = Thread.currentThread(); ThreadLocalMap (threadLocalMap) = getMap(t); // If ThreadLocalMap is not empty if (map! GetEntry (this) {// Get Entry ThreadLocalMap. // return the result if (e! = null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; }} // otherwise set the initialValue return setInitialValue(); }
The illustration
Here is a picture to help you remember.