大綱:
- 用法
- 源碼
一、用法
ThreadLocal是一個容器,顧名思義就是把一個變量存到線程本地。
class Test { public static void main(String[] args) { new Thread(new TestLocal()).start(); new Thread(new TestLocal()).start(); new Thread(new TestLocal()).start(); } } class TestLocal implements Runnable { ThreadLocal<String> localName = new ThreadLocal<>(); @Override public void run() { localName.set(Thread.currentThread().getName()); System.out.println(localName.get()); } } /**結果: * Thread-0 * Thread-1 * Thread-2 */
二、源碼
ThreadLocal是線程本地變量,因此每個Thread對象內部必然存儲ThreadLocal,ThreadLocal作為key,存儲在ThreadLocalMap中。
class Thread { ThreadLocal.ThreadLocalMap threadLocals = null; //每個線程對象內部維護了一個ThreadLocal.ThreadLocalMap。 ... }
ThreadLocal主要方法就是set,get
- set:
public class ThreadLocal<T> { static class ThreadLocalMap {...} //ThreadLocalMap是ThreadLocal的靜態內部類 ... public void set(T value) { Thread t = Thread.currentThread(); //拿到當前線程 ThreadLocalMap map = getMap(t); //取出線程維護的ThreadLocalMap if (map != null) map.set(this, value); //ThreadLocalMap的key為當前ThreadLocal對象,value就是我們需要存儲的變量 else createMap(t, value); //該線程第一次使用ThreadLocal.set時創建ThreadLocalMap對象,並賦值。 } void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); } ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
... }
- get:
public class ThreadLocal<T> { public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); //從當前線程取出ThreadLocalMap if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); //以當前ThreadLocal對象為key取出ThreadLocalMap.Entry if (e != null) { T result = (T)e.value; return result; } } return setInitialValue(); //如果這個ThreadLocal對象沒有賦值直接get,會給它賦值為null並返回。 } private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; } protected T initialValue() { return null; }
... }
ThreadLocal get、set思想小結:
- 拿到當前線程對象。
- 拿到線程對象內部維護的ThreadLocalMap對象。
- 一個線程對象中只有一個ThreadLocalMap對象,所有ThreadLocal對象及這個ThreadLocal對象存儲的值都以key-value的形式存在ThreadLocalMap中。(ThreadLocalMap的key是ThreadLocal對象,value是需要存儲的變量。)