ThreadLocal说明
通常,程序中的对象在多线程下,数据都是竞争共享的。但是,有一个类例外,他生成的实例是线程私有的,ThreadLocal。ThreadLocal生成的对象,线程私有,这是怎么做到的呢?
先看个实例:
public class Test { private ThreadLocal<String> stringThreadLocal = new ThreadLocal<>() ; private ThreadLocal<String> stringThreadLocal2 = new ThreadLocal<>() ; public void print() { System.out.println("threadName:" + Thread.currentThread().getName() + ",value:" + stringThreadLocal.get()); System.out.println("threadName:" + Thread.currentThread().getName() + ",value:" + stringThreadLocal2.get()); } public void setValue(String value) { stringThreadLocal.set(value); stringThreadLocal2.set(value + "——2"); } public static void main(String[] args) throws InterruptedException { Test test = new Test() ; test.setValue("test0"); test.print(); Thread thread1 = new Thread(new Runnable() { @Override public void run() { test.setValue("test1"); test.print(); } }) ; thread1.start(); Thread.sleep(1000); test.print(); } }
输出:
threadName:main,value:test0 threadName:main,value:test0——2 threadName:Thread-0,value:test1 threadName:Thread-0,value:test1——2 threadName:main,value:test0 threadName:main,value:test0——2
从输出结果,看出stringThreadLocal和stringThreadLocal2结果不同,大家可能好理解;但是线程main,和线程 Thread-0 从属性stringThreadLocal和stringThreadLocal2获取的值是不同的,就不是很好理解了。
其实Thread类有一个map,存放相同线程不同ThreadLocal对象对应的值(key为ThreadLocal,value为需要存储的值);ThreadLocal就是对线程Thread内部这个map的管理,不同的线程获取的map不同,不同的ThreadLocal获取的value也不同。
如下ThreadLocal源码:
public T get() { // 获取当前线程 Thread t = Thread.currentThread(); // 获取当前Thread的map ThreadLocalMap map = getMap(t); if (map != null) { // 获取当前ThreadLocal对象对应的entry ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); } // 获取当前线程对应的map ThreadLocalMap getMap(Thread t) { return t.threadLocals; } public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
松下问童子,言师采药去。
只言此山中,云深不知处。