版权声明:本文为博主原创文章,欢迎大家转载!
转载请标明出处: http://blog.csdn.net/guiying712/article/details/79250212 ,本文出自:【张华洋的博客】
ThreadLocal 提供了线程本地变量。这些变量不同于普通变量,每个线程都可以通过 ThreadLocal 的 get 或 set 方法访问这个线程自己的变量,独立初始化变量的副本。ThreadLocal 实例通常在其他类中是 private static 域,它希望将自己的状态与一个线程关联起来。
说的通俗点就是:如果我们想要让一个变量在每一个线程中都拥有独立的值,就需要用到ThreadLocal。
验证线程变量的隔离性
我们先写一段 Android 测试代码:
public class ThreadTestActivity extends AppCompatActivity {
private static final String TAG = "ThreadTestActivity ";
private static ThreadLocal<String> mStringThreadLocal = new ThreadLocal<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_acc);
mStringThreadLocal.set("[Thread#main]");
Log.e(TAG, "[Thread#main] ThreadLocal String =" + mStringThreadLocal.get());
new Thread("Thread#1") {
@Override
public void run() {
mStringThreadLocal.set("[Thread#1]");
Log.d(TAG, "[Thread#1] ThreadLocal String =" + mStringThreadLocal.get());
}
}.start();
new Thread("Thread#2") {
@Override
public void run() {
Log.w(TAG, "[Thread#2] ThreadLocal String =" + mStringThreadLocal.get());
}
}.start();
}
}
程序运行的结果如下图所示:
从图中的运行结果来看,第一次在主线程中调用成员变量 mStringThreadLocal 的 set 方法保存了“[Thread#main]”,所以在主线程中调用 get方法 时返回的值是 “[Thread#main]” ;
然后我们在子线程Thread#1中保存了“[Thread#1]”,调用 get方法 时返回的值是 “[Thread#1]” ;
最后我们在子线程Thread#2中没有保存任何内容,直接调用 get方法 时返回的值是 null。
类ThreadLocal解决的是变量在不同线程间的隔离性,也就是不同线程拥有自己的值,不同线程中的值 是可以放入 ThreadLocal 中进行保存的。
ThreadLocal 源码解析
那么ThreadLocal 是如何做到的呢?我们先看下ThreadLocal 的set()方法:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
//如果当前线程的ThreadLocalMap为空,就new一个Map,否则以当前ThreadLocal对象为key值,存入线程的Map中
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
在 set() 方法中,首先拿到了当前所在线程,就是我们调用ThreadLocal 的 set() 方法时所在的线程,然后执行了 getMap() 方法:
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
getMap()方法返回了当前线程所持有的ThreadLocalMap,我们进入 Thread 类中,CTRL+F 搜索 threadLocals,可以找到 Threadd 的成员变量 threadLocals :
ThreadLocal.ThreadLocalMap threadLocals = null;
也就是说,每一个 Thread 类中都持有一个ThreadLocal.ThreadLocalMap。而我们需要保存的变量值就是保存在这个线程的 ThreadLocalMap 中的。
ThreadLocal的代码总体比较简单,没有什么可讲的,我们直接进入ThreadLocal中的嵌套内部类ThreadLocalMap的实现,这里才是关键。