ThreadLocal

2019-10-09  本文已影响0人  追梦小蜗牛
1.jpg

简介:

ThreadLocal是一个关于创建线程局部变量的类。通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。而使用ThreadLocal创建的变量只能被当前线程访问,其他线程则无法访问和修改。Synchronized用于线程间的数据共享,而ThreadLocal则用于线程间的数据隔离,锁机制:Synchronized是时间换取空间,ThreadLocal是空间换取时间。也就是说这里面存放的变量都只能被当前线程访问,其他线程干预不了。

源码分析:

/**
 * This class provides thread-local variables.  These variables differ from
 * their normal counterparts in that each thread that accesses one (via its
 * {@code get} or {@code set} method) has its own, independently initialized
 * copy of the variable.  {@code ThreadLocal} instances are typically private
 * static fields in classes that wish to associate state with a thread (e.g.,
 * a user ID or Transaction ID).
 **/

ThreadLocal的内部有两个关键的静态内部类:ThreadLocalMap(哈希表)和Entry,Entry又是ThreadLocalMap的静态内部类。
其中,ThreadLocalMap和线程绑定,Entry和ThreadLocal<K>对象绑定。

    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);
            if (e != null) {
                @SuppressWarnings("unchecked")
                T result = (T)e.value;
                return result;
            }
        }
        return setInitialValue();
    }

get数据的流程:

  1. 首先获取到当前线程
  2. 根据当前线程获取绑定的ThreadLocalMap:return t.threadLocals;,threadLocals这个变量在Thread类里面定义。
  3. 判断map对象是否为null,是:构造一个ThreadLocalMap,把initialValue()这个方法的返回值设置到对应的ThreadLocalMap对象里面,并返回。否:直接从ThreadLocalMap里面取出Entry,然后再从过年Entry里面取出value属性的值。下图是构造函数的内容:
        ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
            table = new Entry[INITIAL_CAPACITY];
            int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
            table[i] = new Entry(firstKey, firstValue);
            size = 1;
            setThreshold(INITIAL_CAPACITY);
        }

底层的数据结构是一个Entry数组,也就是哈希表。

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null) {
            map.set(this, value);
        } else {
            createMap(t, value);
        }
    }

set数据的流程:

  1. 首先获取到当前线程
  2. 根据线程获取ThreadLocalMap
  3. 判断map是否为null,是:构造ThreadLocalMap,在构造方法里面进行赋值,否:直接把值设置进去。

场景:

随便聊聊

好久没有正式写技术博客了,以前断断续续的在其他地方都有写过,也都没有一直坚持写下去,形成系统。也不想给自己立下什么flag之类的,学习是内在驱动的,说再多也么用。随着时间的流逝,总结一些东西,写下心得体会,感觉越来越重要了,沉下心来继续学习。

上一篇下一篇

猜你喜欢

热点阅读