1. ThreadLocal定义:线程变量,是一个以ThreadLocal对象为键,任意对象为值得存储结构。
2. 作用:提供线程内得局部变量,在线程的生命周期内起作用,在本线程内随时可取,隔离其它的线程。
下面写了一个简单的例子:
/** * 是一个以ThreadLocal对象为键,任意对象为值得存储结构; * 一个线程可以根据一个ThreadLocal对象查询到绑定在这个线程上得一个值 */ public class Profiler { private static ThreadLocal<Long> TIME_THREADLOCAL = new ThreadLocal<Long>(){ //设定初始值 @Override protected Long initialValue() { return System.currentTimeMillis(); } }; //为ThreadLocal设置指定的值 public static final void begin(){ TIME_THREADLOCAL.set(System.currentTimeMillis()); //set() 设置ThreadLocal中的值 } public static final Long end(){ return System.currentTimeMillis() - TIME_THREADLOCAL.get(); //get()获取ThreadLocal中的值 } public static void main(String[] args) throws InterruptedException { Profiler.begin(); TimeUnit.SECONDS.sleep(1); System.out.println("Cost: "+Profiler.end()+" mills"); } }
这段代码,首先设置一个当前系统时间为初始值,使线程睡眠一秒,调用end()方法,查看begin()和end()方法所运行的时间,输出结果为:
通过上面,对ThreadLocal有了一定的了解。
3. ThreadLocal中方法:
get():获取ThreadLocal上绑定的值;
set():为ThreadLocal设定值;
remove():将当前线程的ThreadLocal绑定的值删除。
4. ThreadLocal的实现:(JDK1.8ThreadLocal源码)
下面看一下get()方法的源码:
/** * Returns the value in the current thread's copy of this * thread-local variable. If the variable has no value for the * current thread, it is first initialized to the value returned * by an invocation of the {@link #initialValue} method. * * @return the current thread's value of this thread-local */ public T get() { Thread t = Thread.currentThread(); //获取当前线程 ThreadLocalMap map = getMap(t); //根据当前线程获取一个map,看后面getMap()源码 if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); //如果map不为空 if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; //返回map中的value } } return setInitialValue(); //如果map为空,设置初始值 }getMap()的源码:
/** * Get the map associated with a ThreadLocal. Overridden in * InheritableThreadLocal. * * @param t the current thread * @return the map */ ThreadLocalMap getMap(Thread t) { return t.threadLocals; //返回一个ThreadLocalMap对象 }
setInitialValue函数的源码:
/** * Variant of set() to establish initialValue. Used instead * of set() in case user has overridden the set() method. * * @return the initial value */ 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; }
createMap函数的源码:
/** * Create the map associated with a ThreadLocal. Overridden in * InheritableThreadLocal. * * @param t the current thread * @param firstValue value for the initial entry of the map */ void createMap(Thread t, T firstValue) { t.threadLocals = new ThreadLocalMap(this, firstValue); }
通过上面对get()方法的源码的简单分析,总结出:
每个Thread维护一个ThreadLocalMap映射表,这个映射表的key是ThreadLocal实例本身,value是真正需要存储的Object。