简介:
ThreadLocal可以实现线程内部存储数据,数据存储以后,只有指定线程可以得到存储数据。使用方式如下:
public class Main6Activity extends AppCompatActivity {
ThreadLocal<String> threadLocal;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main6);
threadLocal = new ThreadLocal<>();
threadLocal.set("哈哈哈");
Log.e("TAG",threadLocal.get());
new Thread(new Runnable() {
@Override
public void run() {
threadLocal.set("呵呵呵");
Log.e("TAG",threadLocal.get());
}
}).start();
}
}
2019-12-23 15:50:12.866 16793-16793/com.example.recyclearapplication E/TAG: 哈哈哈
2019-12-23 15:50:12.867 16793-16824/com.example.recyclearapplication E/TAG: 呵呵呵
可以看到同一个ThreadLocal对象在不同的线程中存取数据,获取的数据也将不同。接下来我们通过看源码分析:
get()方法源码:
public T get() {
//获取当前线程
Thread t = Thread.currentThread();
//获取当前线程的ThreadLocalMap 对象
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();
}
//获取当前线程的threadLocals变量
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
set()源码解析:
public void set(T value) {
//获取当前线程
Thread t = Thread.currentThread();
//获取当前线程的ThreadLocalMap 对象
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
//ThreadLocalMap 对象为null时创建
createMap(t, value);
}
//为当前线程初始化ThreadLocalMap对象
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
ThreadLocalMap
其实是ThreadLocal
的一个静态内部类,其存储结构类似于Map
,它以键值对存储数据。而在java中每一个线程都维护了一个ThreadLocalMap
对象。因此ThreadLocal
存取数据时其实就是先获取当前线程的ThreadLocalMap
对象,然后以ThreadLocal
对象作为key
值存到线程内部的ThreadLocalMap
对象。因此我们使用同一个ThreadLocal
对象在不同的线程中存数据获时取到的值也是不同,原因就是我们数据是存在不同的ThreadLocalMap
对象中。
总结:
new Thread(new Runnable() {
@Override
public void run() {
fun1(context);
threadLocal.set("呵呵呵");
Log.e("TAG",threadLocal.get());
}
}).start();
public void fun1(String context){
//执行业务逻辑
...
省略n行代码
...
fun2(context);
}
public void fun2(String context){
//执行业务逻辑
...
省略n行代码
...
fun3(context);
}
public void fun3(String context){
//执行业务逻辑
...
省略n行代码
...
fun4(context);
}
public void fun4(String context){
//执行业务逻辑
...
省略n行代码
...
}
ThreadLocal可以实现线程数据隔离,它适应在某些数据的作用域为线程的情况下。例如上诉代码我们在一个线程中执行异步操作,整个过程需要调用很多方法,并且我们每一个方法都需要传一个上下文参数,调用逻辑很复杂。这时候我们就可以使用ThreadLocal来解决。
new Thread(new Runnable() {
@Override
public void run() {
//threadLocal存数据
threadLocal.set(context);
Log.e("TAG",threadLocal.get());
fun1();
}
}).start();
}
public void fun1(){
String context = threadLocal.get();
//执行业务逻辑
...
省略n行代码
...
fun2();
}
public void fun2( ){
String context = threadLocal.get();
//执行业务逻辑
...
省略n行代码
...
fun3();
}
public void fun3( ){
String context = threadLocal.get();
//执行业务逻辑
...
省略n行代码
...
fun4();
}
public void fun4(){
String context = threadLocal.get();
//执行业务逻辑
...
省略n行代码
...
}