看到ThreadLocal 有没有想起来 Thread 这个类?
那么就来说说ThreadLocal 是干嘛的吧!
作用:
ThreadLocal是一个线程内部的数据存储类。通过它可以在指定线程中存储数据,并获取到指定线程中的数据。
那么就跟着我一步步来解开疑惑吧~~
step1:
先实例化一个对象。
private ThreadLocal<Boolean> mBooleanThreadLocal = new ThreadLocal<Boolean>();
step2: 开启两个线程
mBooleanThreadLocal.set(true);
Log.d(Tag, "getThread()-----------0" + Thread.currentThread() + "=" + mBooleanThreadLocal.get());
new Thread(new Runnable() {
@Override
public void run() {
mBooleanThreadLocal.set(false);
Log.d(Tag, "getThread()---------1" + Thread.currentThread() + "=" + mBooleanThreadLocal.get());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
Log.d(Tag, "getThread()---------2" + Thread.currentThread() + "=" + mBooleanThreadLocal.get());
}
}).start();
大家可以猜想一下会出现什么样的值?
——-0 == true;
——-1 == false;
——-2 == true or false; 是不是还需要看那个线程先执行是吗?
答案是null 不知道看到这个答案是不是有点好奇为什么?
那我们来看下这个函数—- mBooleanThreadLocal.set(false);
/**
* Sets the value of this variable for the current thread. If set to
* {@code null}, the value will be set to null and the underlying entry will
* still be present.
*
* @param value the new value of the variable for the caller thread.
*/
public void set(T value) {
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values == null) {
values = initializeValues(currentThread);
}
values.put(this, value);
}
解释一下:
获取当前线程,在得到当前线程内部专门用于存储ThreadLocal的数据。
,然后再把这个value 值 存放到—-对应的这个线程 key.
在看一下怎么取出这个值的—— mBooleanThreadLocal.get()
/**
* Returns the value of this variable for the current thread. If an entry
* doesn't yet exist for this variable on this thread, this method will
* create an entry, populating the value with the result of
* {@link #initialValue()}.
*
* @return the current value of the variable for the calling thread.
*/
@SuppressWarnings("unchecked")
public T get() {
// Optimized for the fast path.
Thread currentThread = Thread.currentThread();
Values values = values(currentThread);
if (values != null) {
Object[] table = values.table;
int index = hash & values.mask;
if (this.reference == table[index]) {
return (T) table[index + 1];
}
} else {
values = initializeValues(currentThread);
}
return (T) values.getAfterMiss(this);
}
解释一下:
获取到这个线程对象,在获取到在这个线程保存的值,找到它在 set 时候 table[] 存放的位置信息。
1. 如果找到了 把存放的值返回回去。
2. 为什么会出现 线程——2 为 null的时候。
这是为什么啦?
可以看到 return (T) values.getAfterMiss(this);
然后就可以看到这个方法了
protected T initialValue() {
return null;
}
参考:艺术探索第十章。
结束:
看到这些以上的解释,也就解开了我们开始疑惑了吧。
期待我下一篇的运行时注解吧!