大纲:
用法
源码
一、用法
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<>(); @Overridepublic 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); //取出线程维护的ThreadLocalMapif (map != null) map.set(this, value); //ThreadLocalMap的key为当前ThreadLocal对象,value就是我们需要存储的变量elsecreateMap(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); //从当前线程取出ThreadLocalMapif (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); //以当前ThreadLocal对象为key取出ThreadLocalMap.Entryif (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);elsecreateMap(t, value);return value; }protected T initialValue() {return null; }
...}
ThreadLocal get、set思想小结:
拿到当前线程对象。
拿到线程对象内部维护的ThreadLocalMap对象。
一个线程对象中只有一个ThreadLocalMap对象,所有ThreadLocal对象及这个ThreadLocal对象存储的值都以key-value的形式存在ThreadLocalMap中。(ThreadLocalMap的key是ThreadLocal对象,value是需要存储的变量。)
联系客服