先说一下ThreadLocal是什么吧
——ThreadLocal是一种能保证线程间数据隔离,线程间数据操作互不干扰,能保证高并发下线程安全类似hashMap的数据结构
请看下面两段代码
Demo1 :
图片说明
—— 线程1通过ThreadLocal绑定value到当前线程,接着从当前线程获取到value;线程2通过ThreadLocal.get()获取到的是null
Demo2 :
图片说明
—— main线程通过threadLocal绑定"main"到main线程,线程1和线程2都获取不到value

由此可见通过ThreadLocal可以获取当前线程所绑定的数据,我觉得ThreadLocal更像是一个工具类,因为真正跟当前线程持有的数据相挂钩的是Thread.concurrentThread();
下面请看ThreadLocal提供的get()方法的源码:
图片说明
首先通过Thread.concurrentThread()得到当前线程t,然后通过getMap方法获取到ThreadLocalMap,ThreadLocalMap就是当前线程存储数据的容器,接着对map判断是否为null
如果!=null 则调用map的getEntry(this)方法(this就是当前的threadLocal对象),返回的是一个Entry,注意ThreadLocalMap就是一个个Entry组成的,跟hashMap不同的是,此时的entry内部不会形成链表也不会形成红黑树,因为
根本没有next或者left、right,继续返回result;
看到这,想必大家心里已经有个底了,我们继续看看set()方法干了什么
图片说明
首先依然是得到当前的线程对象,继续调用getMap方法,看当前线程到底有没有存储数据的容器,接着判断容器对象是否为空。如果不为空,那就往这个容器里面塞数据,数据肯定是key-value形式的,
此时的key是this,也就是当前的threadLocal对象,如果容器对象为空,就调用createMap()创建ThreadLocalMap容器对象。

既然是map肯定有hash冲突,来看看ThreadLocal怎么解决hash冲突的
点开ThreadLocalMap的set()
图片说明

每个ThreadLocal对象都有一个hash值threadLocalHashCode,每初始化一个ThreadLocal对象,hash值就增加一个固定的大小0x61c88647。
在插入过程中,根据ThreadLocal对象的hash值,定位到table中的位置i,过程如下:
如果当前位置是空的,那么正好,就初始化一个Entry对象放在位置i上;
不巧,位置i已经有Entry对象了,如果这个Entry对象的key正好是即将设置的key,那么重新设置Entry中的value;
很不巧,位置i的Entry对象,和即将设置的key没关系,那么只能找下一个空位置;