Android开发——ThreadLocal功能介绍

时间:2022-01-23 14:28:55

1.使用场景以及作用介绍

(1)ThreadLocal适用于某些数据以线程为作用域并且不同线程具有不同数据副本的场景。

比如对于Handler来说,它需要获取当前线程的Looper,很显然Looper的作用域就是线程并且不同线程具有不同的Looper,这个时候通过ThreadLocal就可以轻松实现Looper在线程中的存取。

(2)ThreadLocal的另一个使用场景是复杂逻辑下的对象传递。

比如监听器的传递,有时一个线程中的任务过于复杂,又需要监听器贯穿整个线程的执行过程,这时就可以使用ThreadLocal,这样就可以让监听器作为线程内的全局对象而存在,在线程内部只要通过get方法就可以获取到监听器。每个监听器对象都在自己的线程内部存储。

如果不这样做,我们可能将监听器作为函数参数传递,但是这样会很麻烦,降低代码的可读性。或者我们会将监听器作为静态变量供线程访问,但是100个线程就需要100个静态的监听器对象,显然是无法接受的。

2.  使用实例

//首先定义一个ThreadLocal对象,选择泛型为Boolean类型
private ThreadLocal<Boolean> mThreadLocal = new ThreadLocal<Boolean>(); //在主线程、子线程1、子线程2中去设置访问它的值
mThreadLocal.set(true);
System.out.println("Main " + mThreadLocal.get()); new Thread("Thread#1"){
@Override
public void run() {
mThreadLocal.set(false);
System.out.println("Thread#1 " + mThreadLocal.get());
}
}.start(); new Thread("Thread#2"){
@Override
public void run() {
System.out.println("Thread#2 " + mThreadLocal.get());
}
}.start();

输出结果如下:

Main true
Thread#1 false
Thread#2 null


3.  原理介绍

不同的线程访问同一个ThreadLocal获取到的值是不一样的,这是因为,在set方法中,首先通过Thread.currentThread()获取当前线程,Thread类的内部有一个专门用于存储线程ThreadLocal数据的成员Value,通过下面方法获得。

Value value = values(Thread.currentThread());

拿到value后,value对象内部有一个数组:private Object[]table,ThreadLocal的值就存在这个table中,最后通过value的put方法,将最初set方法传递进来的值,根据一定的算法放入table数组中。取数据则通过get方法,依据算法的逆来获取。

set方法源码如下,get源码略。

public void set(T value){
Thread currentThread = Thread.currentThread();
Value values = values(currentThread);
if(values == null){
//初始化操作
values = initializeValues(currentThread);
}
values.put(this,value);
}

总结:ThreadLocal的set和get操作,对象都是当前线程的Value类实例中的table数组,显然不同线程,数组不同,因此ThreadLocal可以在多线程中互不干扰地存储和修改数据。

Android开发——ThreadLocal功能介绍

相关文章