ThreadLocal原理

    在学习消息机制的时候,了解到了ThreadLocal这个类,在这里分享给大家,希望对大家有所帮助。
    首先我们来看一组代码:
    ThreadLocal<String> local1 = new ThreadLocal();
    ThreadLocal<String> local2 = new ThreadLocal();

    new Thread(){
          @Override
          public void run() {
              local1.set("thread1");
              Log.d("----thread1----" + local1.get());
              Log.d("----thread1----" + local2.get());
          }
      }.start();
    new Thread(){
          @Override
          public void run() {
              local2.set("thread2");
              Log.d("----thread2----" + local1.get());
              Log.d("----thread2----" + local2.get());
          }
      }.start();
    运行结果:!(https://img-blog.csdn.net/20160815174829834)
    我们可以发现在第一个线程中分明执行了local1.set(),也能通过local1.get()获取到刚刚设置的值,但是在第二个线程中local1.get()取值却为null呢?
    带着这个疑问我们来看一下ThreadLocal的get和set方法
public void set(T value) {
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values == null) {
            values = initializeValues(currentThread);
        }
        values.put(this, value);
    }
     在外界调用set()之后,首先会通过values方法获取当前线程中的ThreadLocal的数据,数据存储在当前
线程的localValues中,如果localValues为null,就对其进行初始化,再将值进行存储。接下来我们来看看存 
储
void put(ThreadLocal<?> key, Object value) {
            cleanUp();

            // Keep track of first tombstone. That's where we want to go back
            // and add an entry if necessary.
            int firstTombstone = -1;

            for (int index = key.hash & mask;; index = next(index)) {
                Object k = table[index];

                if (k == key.reference) {
                    // Replace existing entry.
                    table[index + 1] = value;
                    return;
                }

                if (k == null) {
                    if (firstTombstone == -1) {
                        // Fill in null slot.
                        table[index] = key.reference;
                        table[index + 1] = value;
                        size++;
                        return;
                    }

                    // Go back and replace first tombstone.
                    table[firstTombstone] = key.reference;
                    table[firstTombstone + 1] = value;
                    tombstones--;
                    size++;
                    return;
                }

                // Remember first tombstone.
                if (firstTombstone == -1 && k == TOMBSTONE) {
                    firstTombstone = index;
                }
            }
        }
     从这段代码中我们可以看出,key和value值在table数组中前后位的关系,注意这里是Values类中的方 
 法,也就是说对应的key、value值的存储是对对应线程localValues对象中table变量的操作。
 接下来我们再来看一下get方法
public T get() {
        // Optimized for the fast path.
        Thread currentThread = Thread.currentThread();
        Values values = values(currentThread);
        if (values != null) {
            Object[] table = values.table;
            int index = hash & values.mask;
            if (this.reference == table[index]) {
                return (T) table[index + 1];
            }
        } else {
            values = initializeValues(currentThread);
        }

        return (T) values.getAfterMiss(this);
    }
    get方法逻辑很清晰,取当前Thread中的localValues对象,如果为null则返回初始值(默认初始值为
null),当然初始方法是可以重写的,不为空则取出table找到对应ThreadLocal的value。
候,比如Looper。
   个人觉得ThreadLocal类也为我们在解决实际问题中提供了一种思路,不以ThreadLocal为数据存储容器
而是以不同的作用域为存储容器,使用复杂度、项目耦合度都有所改善
有问题欢迎指正=。=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值