我们在说明handler原理和AsyncTask原理的时候都提到了ThreadLocal,当时没有细说,现在来介绍一下这个类
ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只有在指定线程中可以获取到存储的数据,对于其它线程来说无法获取到数据.
什么意思?看代码更明白
public class MainActivity extends AppCompatActivity {
//这里的泛型我们使用String,具体使用什么跟实际需求有关
private ThreadLocal<String> threadLocal;
private ThreadLocal<Integer> threadLocal2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
threadLocal = new ThreadLocal<>();
threadLocal2 = new ThreadLocal<>();
threadLocal.set("main");
final Thread thread1 = new Thread(){
@Override
public void run() {
threadLocal.set("1");
threadLocal2.set(1111111);
System.out.println(Thread.currentThread().getName()+" :"+threadLocal.get());
System.out.println(Thread.currentThread().getName()+" :"+threadLocal2.get());
}
};
final Thread thread2 = new Thread(){
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" :"+threadLocal.get());
}
};
thread1.setName("线程1");
thread2.setName("线程2");
thread1.start();
thread2.start();
System.out.println(Thread.currentThread().getName()+" :"+threadLocal.get());
}
}
查看结果:
System.out: 线程1 :1
System.out: main :main
System.out: 线程2 :null
System.out: 线程1 :1111111
分析:虽然只有一个ThreadLocal实例,但是我们在不同线程为其赋值,然后在各自线程得到自己赋的值,这就很好的说明了ThreadLocal的特点
线面通过源码看看为什么会这样
先看set()方法
public void set(T value) {
Thread t = Thread.currentThread();
//getMap()方法就一句话:t.threadLocals,这个值默认是null
//每个线程都维护了一个ThreadLocalMap,简单说ThreadLocalMap就是一个最终用来存储的容器
ThreadLocalMap map = getMap(t);
if (map != null)
//key值是ThreadLocal对象,因为我们可以创建多个ThreadLocal对象来存储不同的数据,
// value是设置的值
map.set(this, value);
else
//创建ThreadLocalMap并存储
createMap(t, value);
}
然后看看get()方法
public T get() {
Thread t = Thread.currentThread();
//获取当前线程的存储容器
ThreadLocalMap map = getMap(t);
//不为空说明已经存储过值了,然后取值
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
//如果还没设置过值,则返回一个初始化的值
return setInitialValue();
}
看到这,应该明白ThreadLocal的奥秘了吧
网友评论