美文网首页
ThreadLocal的作用以及实现原理

ThreadLocal的作用以及实现原理

作者: 三台东 | 来源:发表于2018-07-22 16:58 被阅读7次
     ThreadLocal简介

ThreadLocal是一个线程内部的数据存储类,通过它可以在指定的线程中存储数据,数据存储以后,只能在指定的线程中获取存储的数据,对于其他线程来说则是无法获取到的。Looper、ActivityThead以及AMS中都用到了TheadLocal。

     TheadLocal的使用场景

一、某些数据是以线程为作用域并且不同线程具有不同的数据副本。比如 Handler,它需要获取当前线程的Looper,Looper的作用域就是线程并且不同线程对应不同的Looper,此时可以通过ThreadLocal实现Looper在线程中的存取。
二、复杂逻辑下的对象传递。比如监听器的传递,采用ThreadLocal可以让监听器作为线程内的全局对象存在,在线程内部可以通过get方法获取到监听器。

     ThreadLocal简单使用以及原理分析

首先,举一个简单的例子演示ThreadLocal的使用场景。


image.png

分别在主线程以及两个子线程中,设置同一个ThreadLocal对象中值并通过get方法将结果打印出来。


image.png
从结果可以得出:虽然在不同线程中访问的是同一个ThreadLocal对象,但是获取到的值却是不同的,那为什么会有这样的结果出现呢?其实是因为ThreadLocal内部会从各自的线程中取出一个数组,再从数组中根据当前ThreadLocal的索引去查找对应的value值,不同的线程中的数组是不同的,这就造成ThreadLocal在不同线程中为维护的数据是互不干扰的。

下面分析ThreadLocal的内部实现,主要从分析其get以及set方法入手。

首先看ThreadLocal的set方法。如图所示:


image.png

上面的一段English解释:设置当前线程的本地变量副本。
从源码中可以看出,首先通过getMap方法传递当前线程,返回一个与ThreadLocal相关联的ThreadLocalMap对象,ThreadLocalMap是一个定制的哈希映射,用于维护当前线程中的本地值。如果获取到当前线程中的ThreadLocalMap不是空的话,就设置传入的值,否则创建一个ThreadLocalMap再设置值。
继续跟踪下map.set()方法,如图所示:


image.png
其中, ThreadLocalMap.Entry中始终使用ThreadLocal作为键,那table中存储的便是所有的ThreadLocal及其所对应的副本的值,再通过遍历查找到存储ThreadLocal相对应的Entry,设置传入的vaule值。

下面看ThreadLocal的get方法。如图所示:


image.png

方法解释:返回当前线程中的这个副本的值。
同样先根据当前线程获取到ThreadLocalMap对象,上面谈到过 ThreadLocalMap.Entry中始终使用ThreadLocal作为键,那进而根据当前的ThreadLocal获取到其对应的Entry对象,,获取到其Vaule即可。其中如果获取到的ThreadLocalMap为空,则返回null。

       总结

从ThreadLocal的set以及get方法可以看出,他们操作的都是当前线程相关的ThreadLocalMap中存储的Entry对象,所以不同线程中访问同一个ThreadLocal的get和set方法,仅作用于各自线程的内部,因此使用ThreadLocal可以在不同线程中不干扰的读写数据。

参考文献:Android艺术开发探索第十章:ThreadLocal的工作原理。

相关文章

网友评论

      本文标题:ThreadLocal的作用以及实现原理

      本文链接:https://www.haomeiwen.com/subject/mxtrmftx.html