jdk学习——ThreadLocal

重点:
① 在ThreadLocal中存储的变量每个线程独有
② ThreadLocal中数据结构存储形式是,在每个线程中放置了一个Map存储当前线程所有的静态变量,而不是在ThreadLocal中放置了一个Map来存储所有线程的私有变量,这样有利于在线程回收之后回收ThreadLocal
③ ThreadLocalMap中解决Hash冲突的方式是逐位向后探测空位
④ 在进行操作的时候,ThreadLocal会顺便清理失效的弱引用
⑤ 在清理失效节点的时候,会尝试调整哈希值到正确的索引槽位,但是不一定会成功
⑥ 如果有在子线程中使用ThreadLocal,可以考虑使用InheritableThreadLocal

1. 底层存储数据结构

ThreadLocal.ThreadLocalMap threadLocals = null;

ThreadLocal使用当前变量存储所有的线程静态数据,这个变量的数据结构是一个内部类,类似于一个HashMap

 	static class Entry extends WeakReference<ThreadLocal<?>> {
   
        Object value;
        Entry(ThreadLocal<?> k, Object v) {
   
            super(k);
            value = v;
        }
    }
    private Entry[] table;
    private int size = 0;

ThreadLocalMap的底层数据结构还是一个哈希桶的形式,entry节点时继承了弱引用类,如果这个节点在比较多的时间并没有被使用过,那么键会被设置为空,随后则会被清理函数移除掉。

另外一点值得注意的是,在这个map中,键值是存储的ThreadLocal变量,而不是存储的线程的变量。
按照通常的理解,我们使用一个ThreadLocal类,从中可以获取当前线程的静态变量。很简单地思路就是在ThreadLocal中持有一个HashMap,Map的键是线程,而值时线程存储的静态变量。但是其实不然,在ThreadLocal中,Map的键是当前的ThreadLocal而非Thread

而对应的ThreadLocalMap类则是直接绑定在Thread类的属性上

大胆地猜想:
假如一个线程被回收,就会被与其相关联的所有ThreadLocal变量进行回收掉。毕竟这个变量是绑定在线程上的。
但是如果按照上述方式使用线程作为键的话,线程终止之后,如果还有地方会来引用这个键,那么其实这个Thread对象会迟迟不能够被回收。当然其ThreadLocal的静态变量也是不会被回收咯

解决hash冲突

 private static int nextIndex(int i, int len) {
   
        return ((i + 1 < len) ? i + 1 : 0);
    }
   private static int prevIndex(int i, int len) {
   
        return ((i - 1 >= 0) ? i - 1 : len - 1);
    }

在处理hash冲突的时候,会使用逐个向后查找空位的方式。这种方式比较笨拙,但是也挺简单的。考虑到一个系统可能并不会有太多的ThreadLocal变量,那其实这种方式也不会很差。

查找一个节点

    private Entry getEntry(ThreadLocal<?> key) {
   
        int i = key.threadLocalHashCode & (table.length - 1);
        Entry e = table[i];
        if (e != null && e.get() == key)
            return e;
        else
            return getEntryAfterMiss(key, i, e);
    }

    private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) {
   
        Entry[] tab = table;
        int len = tab.length;

        while (e != null) {
   
       
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值