Java中ThreadLocal学习
一个ThreadLocal在一个线程中是共享的,在不同线程之间又是隔离的。
每个线程都只能看到自己线程的值,这也就是ThreadLocal的核心作用:实现线程范围的局部变量。
实验
public class test {
private ThreadLocal<Integer> num = new ThreadLocal<Integer>(){
@Override
protected Integer initialValue() {
return 0;
}
};
@Test
public void bbb() throws InterruptedException {
new Thread(new Runnable() {
@Override
public void run() {
num.set(1);
System.out.println("一号线程中的值: " + num.get());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
num.set(3);
System.out.println("二号线程中的值: " + num.get());
}
}).start();
Thread.sleep(1000);
System.out.println("主线程中的值: "+ num.get());
}
}
对同一个变量num在不同的线程中进行操作,得到不同的结果。
实验结果
源码分析
get方法获取当前线程中的变量值。
把当前线程实例存入当前线程对象中的map中去。
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
entry的结构:k是弱引用对象,v是值。
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
设置初始化值。
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;
}
map中的key是当前线程对象,值是调用set方法传进来的值value。
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
总结
向ThreadLocal存入一个值,实际上是向当前线程对象中的ThreadLocalMap存入值,ThreadLocalMap我们可以简单的理解成一个Map,而向这个Map存值的key就是ThreadLocal实例本身。