ThreadLocal原理

来源:互联网 发布:新华书店销售数据 编辑:程序博客网 时间:2024/06/07 16:53
    在学习消息机制的时候,了解到了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();
    运行结果:!(http://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为数据存储容器而是以不同的作用域为存储容器,使用复杂度、项目耦合度都有所改善有问题欢迎指正=。=
0 0
原创粉丝点击