1 What is a ThreadLocal

ThreadLocal, located under the java.lang package, is a class for creating thread-local variables. That is, this variable is scoped by the thread and cannot be accessed by other threads. Variables created using ThreadLocal are normally accessible by any thread, whereas variables created using ThreadLocal can only be accessed by the current thread. Very abstract, look at my application scenario below

Application scenario: When some data is thread-scoped and different threads have different copies of the data, such as Looper, each thread has its own Looper. It’s a bit abstract to describe, but imagine what it would take to implement the Looper for each thread. The solution I came up with was to create a thread-safe Map to maintain data adding, deleting, modifying, and searching. So it feels very convenient to use ThreadLocal to implement this without having to maintain it yourself. That’s why ThreadLocal exists and how it’s used, pretty straightforward ,>

2 How to use ThreadLocal

See looper.java for examples

Static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); Private static void prepare(Boolean quitAllowed) {// Check whether the Looper of this thread is instantiated. = null) { throw new RuntimeException("Only one Looper may be created per thread"); Sthreadlocal. set(new Looper(quitAllowed)); sthreadLocal. set(new Looper(quitAllowed)); }Copy the code

3 Analysis of main methods of ThreadLocal

The main public methods exposed by ThreadLocal are get/set/remove

3.1 the get

Gets the Value of the ThreadLocal instance

Public T get() {T = thread.currentThread (); ThreadLocalMap map = getMap(t); // Get the thread variable t.htreadlocals, which is stored separately for each thread. Value if (map! = null) { ThreadLocalMap.Entry e = map.getEntry(this); // 2 if (e ! = null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } return setInitialValue(); / / 3}Copy the code

To summarize, each thread has a ThreadLocalMap variable, and ThreadLocalMap uses ThreadLocal as its key. So each ThreadLocal value we set is queried by Thread and added to our own private map.

1 the getMap (t)

ThreadLocalMap getMap(Thread t) {return t.htreadlocals; }Copy the code

2 in the map. The getEntry (this)

Private Entry getEntry(ThreadLocal<? Hashcode int I = key.threadLocalHashCode & (table.length-1); Entry e = table[I]; If (e! = null && e.get() == key) return e; Return getEntryAfterMiss(key, I, e); return getEntryAfterMiss(key, I, e); }Copy the code


Private T setInitialValue() {// If the map has not been created or the ThreadLocal instance has not set a specific value T value = initialValue(); T value = initialValue(); T value = initialValue(); T value = initialValue(); Thread t = thread.currentThread (); ThreadLocalMap map = getMap(t); // Create a map and assign a map if (map! = null) map.set(this, value); else createMap(t, value); return value; } // Default is Null protected T initialValue() {return Null; }Copy the code

3.2 the set

Set and update Value

Public void set(T value) {public void set(T value) {public void set(T value) { ThreadLocalMap map = getMap(t); If (map! = null) map.set(this, value); else createMap(t, value); }Copy the code

3.3 remove!!!!!

To remove data

Public void remove() {ThreadLocalMap m = getMap(thread.currentThread ()); if (m ! = null) // Remove data. Emove (this); }Copy the code

There is a memory leak involved here, for example if we don’t use threadLocal.remove to remove data, An entry in a map holds a weak reference to a ThreadLocal. When a thread releases a strong reference to a ThreadLocal instance, that is, the ThreadLocal instance is gc, but the value stored in the map is not reclaimed, and is permanently stored in the map. So there are memory leaks. The best practice is to call remove first when an instance of ThreadLocal needs to be freed.

3.4 other

4 reference

  • Link: www.jianshu.com/p/95291228a…
  • Links to www.cnblogs.com/mingfeng002…