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。