Different threads can get their own data from the same ThreadLocal object.

ThreadLocal.ThreadLocalMap

Inner class of ThreadLocal. An array with the hash value of the ThreadLocal and the Entry element as the value. Inside ThreadLocalMap, a map-like mapping is implemented. The internal Entry inherits WeakReference >, which holds a weak reference to ThreadLocal and holds the value passed in by threadlocal.set (value). >

static class Entry extends WeakReference<ThreadLocal<? >>{
    /** The value associated with this ThreadLocal. */Object value; Entry(ThreadLocal<? > k, Object v) {super(k); value = v; }}Copy the code

ThreadLocal

The get method

public T get(a) {
    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;
            returnresult; }}return setInitialValue();
}
Copy the code

Set method

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

void createMap(Thread t, T firstValue) {
    t.threadLocals = new ThreadLocalMap(this, firstValue);
}
Copy the code

Places to use:

  • Android’s Looper Handler MessageQueue is based on this.
  • .

Example:

public class Main {
    static final ThreadLocal<String> mThreadLocal = new ThreadLocal<>();
    public static void main(String[] args) {
        new Thread("thread1") {
            @Override
            public void run(a) {
                mThreadLocal.set("value1");
                try {
                    Thread.sleep(4000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(currentThread().getName() + " localValue:" + mThreadLocal.get());
            }
        }.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        new Thread("thread2") {
            @Override
            public void run(a) {
                mThreadLocal.set("value2");
                System.out.println(currentThread().getName() + " localValue:"+ mThreadLocal.get()); } }.start(); }}Copy the code

Output:

thread2 localValue:value2
thread1 localValue:value1
Copy the code

Even though they are the same ThreadLocal object and both call the same set GET method, the get method must return the value corresponding to the current thread.