ThreadLocal 使用和源码分析
1 使用场景
ThreadLocal是一个线程的本地变量,也就意味着这个变量是线程独有的,是不能与其他线程共享的。这样就可以避免资源竞争带来的多线程的问题。但是,这种解决多线程安全问题的方式和加锁方式(synchronized、Lock) 是有本质的区别的:
ThreadLocal的使用非常广泛,典型的,mybatis的分页插件PageHelper用的就是ThreadLocal。
在我们日常的开发里,最典型的应用就是例如一个请求(单线程)的执行过程要执行很多方法:a->b->c->d->e,假设方法a要用到一个变量,e也要用到这个变量,如果这个变量一直往下传则会显得很臃肿,这个时候,ThreadLocal是个很好的解决方式
- 传递数据: 每个线程绑定的数据,在需要的地方可以直接获取, 避免参数直接传递带来的耦合问题
- 线程隔离:各线程之间的数据相互隔离却又具备并发性,避免同步方式带来的性能损失。
2 具体实现的原理图
ThreadLocal、Thread、ThreadLocalMap、Entry之间的关系
3 数据结构-解决Hash冲突
3.1 线性探测法(ThreadLocalMap的底层数据结构)
线性探测法(开放地址法的一种): 计算出的散列地址如果已被占用,则按顺序找下一个空位。如果找到末尾还没有找到空位置就从头重新开始找;
3.2 二次探测法(开放地址法的一种)
3.3 链地址法
链地址是对每一个同义词都建一个单链表来解决冲突,HashMap采用的是这种方法;
3.4 多重Hash法
在key冲突的情况下多重hash,直到不冲突为止,这种方式不易产生堆积但是计算量太大;
3.5 公共溢出区法
这种方式需要两个表,一个存基础数据,另一个存放冲突数据称为溢出表;