安卓中ThreadLocal基础

ThreadLocal是Java中用于实现线程局部变量的工具类,它提供了线程私有的数据存储,不同线程间数据互不影响。通过get和set方法,可以在每个线程中独立设置和获取值。其内部使用ThreadLocalMap存储数据,以弱引用的ThreadLocal对象作为键,实际值作为值。在示例代码中展示了如何在主线程和子线程中使用ThreadLocal,展示其线程隔离的特性。
摘要由CSDN通过智能技术生成

在这里插入图片描述

1.ThreadLocal 概念

ThrealLocal 提供线程据局部变量。通过 get 和 set 方法的方法的访问都是线程私有的,独立初始化的变量副本。

通俗来讲:它可以以线程为界限来存储数据,该数据存储后,只有在指定的线程中才能获取到存储的数据,对于其它线程而言该变量为默认初始值(null)。

使用场景:当某些数据以线程为作用域,并且不同的线程数据互相独立的时候,就可以考虑使用 ThreaLocal

2.关键类及方法

ThreadLocal 是一个泛型类,
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Maf8aEkc-1634546667461)(../../pic/image-20211018110506216.png)]

ThreadLocal#get()

public T get() {
   //1.获取当前线程
  Thread t = Thread.currentThread();
   //2.传入线程获取 ThreadLocalMap 对象。
   ThreadLocalMap map = getMap(t);
   if (map != null) {
   //3.如果不为null,传入 ThreadLcoal 获取到ThreadLocalMap.Entry
   ThreadLocalMap.Entry e = map.getEntry(this);
      if (e != null) {
          @SuppressWarnings("unchecked")
          T result = (T)e.value;
          return result;
      }
   }
   //4.为 null 进行初始化
   return setInitialValue();
}

// 2.1ThreadLocal#getMap
ThreadLocalMap getMap(Thread t) {
   return t.threadLocals;
}
//2.2 Thread#threadLocals,线程本地数组存储,由ThreadLocal维护
ThreadLocal.ThreadLocalMap threadLocals = null;

//4.1 初始化ThreadLocaMap。
private T setInitialValue() {
    //初始化为 value = null 
    T value = initialValue();                    
    Thread t = Thread.currentThread();           
    ThreadLocalMap map = getMap(t);              
    if (map != null)                             
        map.set(this, value);                    
    else
        //创建 ThreadLocalMap
        createMap(t, value);                     
    return value;                                
}

//4.2 key 为当前线程的,value 初始为 null
 void createMap(Thread t, T firstValue) {                           
     t.threadLocals = new ThreadLocalMap(this, firstValue);         
 }   

首先获取当前线程的 ThreadLocalMap 变量,如果为 nll,就调用 setInitialValue() 方法进行初始化,默认情况下,initialValue() 的值返回都null,可以重写这个方法设置我们想要的初始值。

可以看到,所有的操作最终都是和当前线程的 ThreadLocalMap 变量打交道。

ThreadLocal#set()

public void set(T value) {            
    Thread t = Thread.currentThread();
    //获取 ThreadLocalMap 用于存储变量值, key 为 ThreadLocal<>
    ThreadLocalMap map = getMap(t);   
    if (map != null)                  
        map.set(this, value);         
    else
        //否则创建 ThreadLocalMap
        createMap(t, value);          
}


在 set() 方法中,先获取到当前线程,然后通过 getMap(Thread t) 方法获取一个 ThreadLocalMap,如果这个 map 不为空的话,就将 ThrealLocal 和 value 设置进去,不然的话就创建一个 ThrealLocalMap 然后再进行设置。

ThreadLocal#ThreadLocalMap

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z4SaZIxV-1634546667464)(../../pic/image-20211018164253058.png)]

ThreadLocalMap 是 ThreadLocal 的一个静态内部类,每一个 Thread 都有一个对应的 ThreadLocalMap。通过 ThreadLocalMap 来存储 ThreadLocal 对象。

//Thread#threadLocals,线程本地数组存储,由ThreadLocal维护
ThreadLocal.ThreadLocalMap threadLocals = null;
//ThreadLocalMap
static class ThreadLocalMap {     
    
    static class Entry extends WeakReference<ThreadLocal<?>> {       
        Object value;                                               
        Entry(ThreadLocal<?> k, Object v) {                         
            super(k);                                               
            value = v;                                               
        }                                                           
    }                                                               
    private static final int INITIAL_CAPACITY = 16;
    //ThreadLocal 存储在 table 数组中。以弱引用的方式的键值对
    private Entry[] table;                                           }     

ThreadLocal 中的 set 和 get 方法,都是操作 ThreadLocal#ThreadLocalMap 中的

private Entry[] table 来保存 ThreadLocal 中的值。

3.示例代码

public class ThreadLocalActivity extends AppCompatActivity {

    private static final String TAG = ThreadLocalActivity.class.getSimpleName();

    private ThreadLocal<String> mMainLocal = new ThreadLocal<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_thread_local);
        mMainLocal.set("第一次赋值");
        Log.i(TAG, "onCreate: mMainLocal = " + mMainLocal.get());

        new Thread("Thread-1") {
            @Override
            public void run() {
                Log.i(TAG, "Thread-1 get : " + mMainLocal.get());
                mMainLocal.set("第二次赋值:");
                Log.i(TAG, "Thread-1 get : " + mMainLocal.get());
            }
        }.start();
    }
}

2021-10-18 10:43:23.470 24428-24428/com.tsp.learn I/ThreadLocalActivity: onCreate: mMainLocal = 第一次赋值
2021-10-18 10:43:23.470 24428-24628/com.tsp.learn I/ThreadLocalActivity: Thread-1 get : null
2021-10-18 10:43:23.471 24428-24628/com.tsp.learn I/ThreadLocalActivity: Thread-1 get : 第二次赋值:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值