首页 > 代码库 > 【原创】源码角度分析Android的消息机制系列(二)——ThreadLocal的工作过程
【原创】源码角度分析Android的消息机制系列(二)——ThreadLocal的工作过程
ι 版权声明:本文为博主原创文章,未经博主允许不得转载。
在上一篇文章中,我们已经提到了ThreadLocal,它并非线程,而是在线程中存储数据用的。数据存储以后,只能在指定的线程中获取到数据,对于其他线程来说是无法获取到数据的,也就是说ThreadLocal可以在多个线程中互不干扰地存储和修改数据。基于ThreadLocal的这一特点,那么当我们在开发中,需要将某些数据以线程作为作用域,并且不同线程具有不同的数据副本的时候,就可以考虑采用ThreadLocal了。
Android的消息机制中也用到了ThreadLocal。Handler需要获取到当前线程的Looper,但是不同线程中的Looper是不同的,此时就可以通过ThreadLocal来实现Looper在线程中的存取了。
下面通过例子来观察下ThreadLocal存储数据的特点。
首先定义一个ThreadLocal对象,然后分别在主线程,子线程1和子线程2中设置和访问它的值,代码如下所示:
private final String TAG=getClass().getSimpleName(); //获取当前类名 private ThreadLocal<Boolean> mBooleanThreadLocal=new ThreadLocal<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mBooleanThreadLocal.set(true); Log.e(TAG, "[mainThread]mBooleanThreadLocal="+mBooleanThreadLocal.get() ); new Thread("Thread1"){ @Override public void run() { super.run(); mBooleanThreadLocal.set(false); Log.e(TAG, "[Thread1]mBooleanThreadLocal="+mBooleanThreadLocal.get() ); } }.start(); new Thread("Thread2"){ @Override public void run() { super.run(); Log.e(TAG, "[Thread2]mBooleanThreadLocal="+mBooleanThreadLocal.get() ); } }.start(); }
日志如下所示:
06-17 16:46:04.663 5300-5300/com.bella.androidart E/ThreadLocalActivity: [mainThread]mBooleanThreadLocal=true 06-17 16:46:04.663 5300-5317/com.bella.androidart E/ThreadLocalActivity: [Thread1]mBooleanThreadLocal=false 06-17 16:46:04.679 5300-5318/com.bella.androidart E/ThreadLocalActivity: [Thread2]mBooleanThreadLocal=null
从上面日志可以看出,虽然在不同线程中访问的是同一个ThreadLocal对象,但是它们通过ThreadLocal获取到的值却是不一样的,这就是ThreadLocal的奇妙之处。ThreadLocal之所以有这么奇妙的效果,是因为不同线程访问同一个ThreadLocal的get方法,ThreadLocal内部会从各自的线程中取出一个数组,然后再从数组中根据当前ThreadLocal的索引去查找出对应的value值。很显然,不同线程中的数组是不同的。
【原创】源码角度分析Android的消息机制系列(二)——ThreadLocal的工作过程