0
点赞
收藏
分享

微信扫一扫

ThreadLocal、InheritableThreadLocal和TransmittableThreadLocal

zhaoxj0217 2022-01-17 阅读 30

因为项目里需要用到线程变量共享,首选使用了ThreadLocal,但是项目里对大数据量处理转了异步操作,所以需要子线程拿到父线程的变量,于是使用了InheritableThreadLocal进行测试,然后发现了一个问题,InheritableThreadLocal必须要线程初始化的时候将inheritableThreadLocals这个变量放到子线程的inheritableThreadLocals这个变量上,但是我们的项目异步又是用得线程池,导致线程复用,线程不会每次都初始化,使用了阿里的TransmittableThreadLocal可以解决线程复用的问题,简单来说,是对线程进行了包装,将变量进行传递

 

ThreadLocal:同一线程内,变量共享,不同线程内变量不共享

InheritableThreadLocal:父子线程内,变量可以共享,子线程必须是新建的,也就是说线程不可以是复用的,子线程是线程池的线程就不可以

TransmittableThreadLocal:解决父子线程内,子线程复用情况,变量共享的问题

详解:(等待补充)

ThreadLocal

set():

public void set(T value) {
        //获取当前线程
        Thread t = Thread.currentThread();
        //获取当前线程的值
        ThreadLocalMap map = getMap(t);
        if (map != null)
            //存在就设置新值
            map.set(this, value);
        else
            //不存在就构建一个ThreadLocalMap对象,存到threadLocals这个变量上
            createMap(t, value);
    }
//线程变量的值放在threadLocals这个变量上
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

private void set(ThreadLocal<?> key, Object value) {

            // We don't use a fast path as with get() because it is at
            // least as common to use set() to create new entries as
            // it is to replace existing ones, in which case, a fast
            // path would fail more often than not.

            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);

            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                ThreadLocal<?> k = e.get();

                if (k == key) {
                    e.value = value;
                    return;
                }

                if (k == null) {
                    replaceStaleEntry(key, value, i);
                    return;
                }
            }

            tab[i] = new Entry(key, value);
            int sz = ++size;
            if (!cleanSomeSlots(i, sz) && sz >= threshold)
                rehash();
        }

get():

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();
    }

    private T setInitialValue() {
        //返回null
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        //有值也要置为null
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

remove():

public void remove() {
         ThreadLocalMap m = getMap(Thread.currentThread());
         if (m != null)
             m.remove(this);
     }

private void remove(ThreadLocal<?> key) {
            Entry[] tab = table;
            int len = tab.length;
            int i = key.threadLocalHashCode & (len-1);
            for (Entry e = tab[i];
                 e != null;
                 e = tab[i = nextIndex(i, len)]) {
                if (e.get() == key) {
                    e.clear();
                    expungeStaleEntry(i);
                    return;
                }
            }
        }
举报

相关推荐

0 条评论