The basic use

// create ThreadLocal<Object> mThreadLocal = new ThreadLocal<Object>() Mthreadlocale.get () // Remove mthreadlocale.remove ();Copy the code

The principle of analysis

ThreadLocal is constructed as follows:

  public ThreadLocal() {
    }
Copy the code

You just create objects, you don’t do much. Set method is as follows:

public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map ! = null) { map.set(this, value); } else { createMap(t, value); } } ThreadLocalMap getMap(Thread t) { return t.threadLocals; } void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }Copy the code

Each Thread holds a ThreadLocalMap, which stores data using the same data structure as a HashMap, using ThreadLocal as the Key.

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

The get method is as follows:

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(); }Copy the code

The ThreadLocalMap is retrieved based on the current thread, and the data with the current ThreadLocal key is retrieved. Remove method is as follows:

public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null) {
             m.remove(this);
         }
     }
Copy the code

This method directly removes the local data in the map that holds the key of the current Thread.

conclusion

  • With ThreadLocal, you can set some thread-private variables on the currently running thread to achieve data isolation between threads.
  • Each Thread (Thread instance) maintains a threadLocalsThreadLocal.ThreadLocalMap, which uses the same data structure as HashMap;
  • ThreadLocal does not store data, but serves as a key for threadLocals and manages data using the get and set methods.
  • A thread can have multiple instances of ThreadLocal holding different values as keys.
  • For each value and assignment, the current thread is retrieved, followed by threadLocals for proper access to thread data.

extension

Why ThreadLocal in Handler ensures one and only one Loop per thread — static constant plus private constructor implementation:

public final class Looper { static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } } public static void prepare() { prepare(true); } private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() ! = null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); }Copy the code
  1. Ensure unique immutable key values by using static constants.
  2. The privatized constructor ensures that Looper is first checked to see if it already exists.

One final note: Since a ThreadLocalMap has the same lifetime as a Thread, memory leaks can occur if the corresponding key is not manually removed. ThreadLocal is used as a key by weak reference, so when a ThreadLocal object is discarded, ThreadLocal is reclaimed even if it is not manually deleted.