ThreadLocal分析
Handler的运行需要MessageQueue和Looper的支持,如果您对这方面不是很熟悉,那么我推荐您阅读这个,或者看Android开发艺术探索,而为了更好的理解Looper,那么ThreadLocal是避不过去的一项
我们都知道,一个线程只能创建一个Looper,那么在这个线程中传递数据的就是ThreadLocal了
ThreadLocal是一个线程内部的数据存储类,他可以在指定的线程中存储数据,然后当然也只能在存储数据的线程来获取数据,来看一个小demo
首先我们定义一个ThreadLocal对象,然后分别在主线程和两个子线程中去设置数据和获取数据
private ThreadLocal<Boolean> mBooleanThreadLocal = new ThreadLocal<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mBooleanThreadLocal.set(true);
Log.d("112233", Thread.currentThread().getName()
+ " = " +
mBooleanThreadLocal.get());
new Thread("Thread #1"){
@Override
public void run() {
super.run();
mBooleanThreadLocal.set(false);
Log.d("112233", Thread.currentThread().getName()
+ " = " +
mBooleanThreadLocal.get());
}
}.start();
new Thread("Thread #2"){
@Override
public void run() {
super.run();
Log.d("112233", Thread.currentThread().getName()
+ " = " +
mBooleanThreadLocal.get());
}
}.start();
}
可以看到这里用的都是同一个LocalThread对象,然后运行程序,看一下log
D/112233: main = true
D/112233: Thread #1 = false
D/112233: Thread #2 = null
我们会发现在不同的线程中获得的值是不同的,下面来分析一下源码,来看一下为什么返回的值不一样
public T get() {
Thread t = Thread.currentThread();//从这里获取当前线程
ThreadLocalMap map = getMap(t);//这里获取当前线程的Map
if (map != null) {
//这里取出由当前threadLocal为key的entry
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;//返回value
}
return setInitialValue();//如果为空,那么初始化
}
-------------------------------------------
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;//这里返回多个threadLocal的对象
}
-------------------------------------------
private T setInitialValue() {
T value = initialValue();//这个方法返回null
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);//如果map存在,则替换掉数据
else
createMap(t, value);//如果map不存在,则创建一个map,数据为null
return value;//最后返回null
}
从get方法我们可以看得出来获取数据是用Thread为参数的,所以说每个线程的数据都不一样。既然这样我们就再来看看set方法
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
我们会发现和上面的setInitialValue()方法差不多,都是调用的map.set()方法,这个方法其实就是一个以当前ThreadLocal为key存储的过程,我们就不细细的去研究了,有兴趣的可以去看一下
至此这个ThreadLocal我们也就研究的差不多了,其实的就是在不同的线程存储不同的数据
ThreadLocal和InheritableThreadLocal
我第一次写那个小demo的时候犯了一个小错误,new对象的时候new成了InheritableThreadLocal,从名字我们也可以看得出来这是一个继承了table的ThreadLocal,关于这两个有什么区别,我推荐您看这个
爱小丽,爱Android