Java interview must ask, ThreadLocal ultimate

Posted by psychohagis on Sun, 30 Jan 2022 08:22:29 +0100

##Foreword
During the interview, it is also common for the interviewer to investigate "ThreadLocal", so it is very necessary to understand it thoroughly
Some interviewers ask straight to the point:

"Do you know ThreadLocal?"
"Tell me about your understanding of ThreadLocal"

Of course, some interviewers will slowly lead to this topic, such as asking "how to prevent your variables from being tampered with by other threads in a multithreaded environment", giving the initiative to yourself, and the rest depends on yourself.
What can ThreadLocal do? Before we understand its application scenario, let's first look at its implementation principle. Only when we know the implementation principle can we judge whether it conforms to our own business scenario.
##What is ThreadLocal
First of all, it is a data structure, a bit like HashMap. It can save "key: value" key value pairs, but only one ThreadLocal can be saved, and the data of each thread does not interfere with each other.

ThreadLocal<String> localName = new ThreadLocal();
localName.set("Zhan Xiaolang");
String name = localName.get();

A ThreadLocal object localName is initialized in thread 1, and a value accounting for Coyote is saved through the set method. At the same time, it is initialized in thread 1 through localName Get () can get the value set before, but if it is in thread 2, it will get a null.
Why and how? However, as I said before, ThreadLocal ensures that the data of each thread does not interfere with each other.
Look at the source code of the set(T value) and get() methods

 public void set(T value) {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null)
        map.set(this, value);
    else
        createMap(t, value);
}

public T get() {
    Thread t = Thread.currentThread();
    ThreadLocalMap map = getMap(t);
    if (map != null) {
        ThreadLocalMap.Entry e = map.getEntry(this);
        if (e != null) {
            @SuppressWarnings("unchecked")
            T result = (T)e.value;
            return result;
        }
    }
    return setInitialValue();
}

ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
}

It can be found that each thread has a ThreadLocalMap data structure. When the set method is executed, its value is saved in the threadLocals variable of the current thread. When the set method is executed, it is obtained from the threadLocals variable of the current thread.
Therefore, the value of set in thread 1 cannot be touched by thread 2, and if it is reset in thread 2, it will not affect the value in thread 1, ensuring that threads will not interfere with each other.
What is the threadloadmap in each thread?
##ThreadLoalMap
This paper analyzes the source code of 1.7.
From the name, you can guess that it is also a data structure similar to HashMap, but the Map interface is not implemented in ThreadLocal.
In threadloadmap, an Entry array with a size of 16 is also initialized. The Entry object is used to save each key value pair, but the key here is always ThreadLocal object. Isn't it amazing? Through the set method of ThreadLocal object, the ThreadLocal object itself is regarded as a key and put into threadloadmap.


It should be noted here that the Entry of threadloadmap inherits the WeakReference. The big difference between threadloadmap and HashMap is that there is no next field in the Entry, so there is no linked list.
##hash conflict
If there is no linked list structure, what if there is a hash conflict?
Let's first look at the implementation of inserting a key value into threadloadmap

private void set(ThreadLocal<?> key, Object value) {
    Entry[] tab = table;
    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;
        }
    }

    tab[i] = new Entry(key, value);
    int sz = ++size;
    if (!cleanSomeSlots(i, sz) && sz >= threshold)
        rehash();
}

Each ThreadLocal object has a hash value threadLocalHashCode. Each time a ThreadLocal object is initialized, the hash value increases by a fixed size 0x61c88647.

During insertion, locate the position i in the table according to the hash value of ThreadLocal object. The process is as follows:
1. If the current location is empty, an Entry object will be initialized and placed at location i;
2. Unfortunately, there is already an Entry object in position i. if the key of this Entry object is exactly the key to be set, reset the value in the Entry;
3. Unfortunately, the Entry object at position i has nothing to do with the key to be set, so you can only find the next empty position;

In this way, when getting, it will also locate the location in the table according to the hash value of the ThreadLocal object, and then judge whether the key in the Entry object of this location is consistent with the key of get. If not, it will judge the next location
It can be found that if the conflict between set and get is serious, the efficiency is very low. Because threadloadmap is an attribute of Thread, even if you control the number of elements set in your own code, you still can't control the behavior of other codes.
##Memory leak
ThreadLocal may lead to memory leakage. Why? Let's first look at the implementation of Entry:

static class Entry extends WeakReference<ThreadLocal<?>> {
    /** The value associated with this ThreadLocal. */
    Object value;

    Entry(ThreadLocal<?> k, Object v) {
        super(k);
        value = v;
    }
}

Through the previous analysis, it has been known that when using ThreadLocal to save a value, an Entry object will be inserted into the array in ThreadLocalMap. It is reasonable that key values should be saved in the Entry object with strong reference, but in the implementation of ThreadLocalMap, the key is saved in the WeakReference object.
This leads to a problem. When ThreadLocal has no external strong reference, it will be recycled during GC. If the thread creating ThreadLocal keeps running, the value in the Entry object may not be recycled and memory leakage may occur.
##How to avoid memory leakage
Since the hidden danger of memory leakage has been found, there are naturally coping strategies. Calling get() and set() of ThreadLocal may clear the Entry object with null key in ThreadLocalMap, so that the corresponding value can not be reached by GC Roots and can be recycled at the next GC. Of course, if you call the remove method, the corresponding Entry object will be deleted.
If you call the remove method after using the set method of ThreadLocal, memory leakage may occur. Therefore, it is very important to develop good programming habits. Remember to call the remove method after using ThreadLocal.

ThreadLocal<String> localName = new ThreadLocal();
try {
    localName.set("Zhan Xiaolang");
    // Other business logic
} finally {
    localName.remove();
}

last
Codeword is not easy. If you think this article is useful to you, please give me some praise! Pay attention to the author, there will be more dry goods to share in the future, please continue to pay attention!

ThreadLocal roughly mentioned this. If you want to know more about Java interview, {you can pay attention to the author or add the author's assistant:} get more relevant notes for the interview and thoroughly understand the Java interview questions. Interview so easy!

~Contact information can be added~
wechat: Mlzg5201314zz
 Buckle: 2967728282///
## summary

This month will be over soon. The little partner who is still looking for a job should be ready. Xiaobian has sorted out the big factory java Most of the programmer interviews involve**Interview questions and answers**Share it for free. I hope it can help you. Friends in need can see the following**Free collection method**!

> [Data collection method: stamp here](https://docs.qq.com/doc/DSmxTbFJ1cmN1R2dB)

![Insert picture description here](https://img-blog.csdnimg.cn/img_convert/a3317115962bb5743608577585a769c9.png)

![Insert picture description here](https://img-blog.csdnimg.cn/img_convert/520d167c917546b30f9703444602d8f6.png)

Way: poke here](https://docs.qq.com/doc/DSmxTbFJ1cmN1R2dB)

[External chain picture transfer...(img-Lp8dkQlN-1623568302752)]

[External chain picture transfer...(img-cEMgwfXR-1623568302756)]

Topics: Java Interview Programmer