Let’s start with the class structure of ThreadLocal.





set(T value)

    /**
     * Sets the current thread's copy of this thread-local variable
     * to the specified value.  Most subclasses will have no need to
     * override this method, relying solely on the {@link #initialValue}
     * method to set the values of thread-locals.
     *
     * @param value the value to be stored in the current thread's copy of
     *        this thread-local.
     */
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if(map ! =null)
            map.set(this, value);
        else
            createMap(t, value);
    }
Copy the code

CurrentThread () gets the Thread instance that is currently calling the set(T value) method.

    /**
     * Returns a reference to the currently executing thread object.
     *
     * @return  the currently executing thread.
     */
    public static native Thread currentThread(a);
Copy the code

It then calls its own getMap(Thread t) method to get the ThreadLocalMap instance, which is important here.

    /**
     * Get the map associated with a ThreadLocal. Overridden in
     * InheritableThreadLocal.
     *
     * @param  t the current thread
     * @return the map
     */
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
Copy the code

That is, ThreadLocalMap instances are held by each Thread instance. ThreadLocalMap is null if the current Thread is null. The createMap(Thread t, t firstValue) method is called.

    /**
     * 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) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }
Copy the code

It is also important to note that ThreadLocal assigns a new instance of ThreadLocalMap to the Thread locals member variable. When ThreadLocalMap is instantiated, a reference to ThreadLocal itself (this) and a value (value) are passed into the constructor. Next, look at the ThreadLocalMap constructor used in the createMap(Thread t, t firstValue) method.

        /** * Construct a new map initially containing (firstKey, firstValue). * ThreadLocalMaps are constructed lazily, so we only create * one when we have 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);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }
Copy the code

The key stored in the Map is of ThreadLocal type, not Thread type.

conclusion

ThreadLocal does not own a ThreadLocalMap instance. Threads do own a ThreadLocalMap instance. ThreadLocal obtains the ThreadLocalMap instance from the current Thread instance, and then operates on the map as if it were the key.

  1. That is, if there are multiple ThreadLocal classes operating on the same thread, the ThreadLocalMap in the thread will have multiple key-value pairs.
  2. A ThreadLocal class can only operate on one key-value per thread. The key is itself, and the type of value can be a self-defined object instance.

nonsense

Here said relatively simple, pure according to their own understanding of the writing. There are many methods that have not been explained, but it is still very understandable. If there is something wrong, please give me more advice.