持续积累ThreadLocal技术的目录
一、先从使用ThreadLocal开始
1、我看到的两种创建方式
1.1 ThreadLocal aThreadLocal = new ThreadLocal<>();
1.2 ThreadLocal aThreadLocal = ThreadLocal.withInitial(…)
1.3 为啥需要1.2提到的创建方式?直接new不就好了?
- JDK源码中,就提到了ThreadLocal.withInitial(…):

2、创建好了后,在使用aThreadLocal时,会涉及到3种重要的API
2.0 在理解3种API之前,又不得不了解下ThreadLocal内部的存储结构(不清楚存储结构,何谈对其的操作?)
2.0.1 3种API的概述
- set方法:aThreadLocal.set(…)
- get方法:aThreadLocal.get()
- remove方法:aThreadLocal.remove()
2.0.2 ThreadLocal内部的存储结构
- 图解:

2.1 set方法:aThreadLocal.set(…)
2.1.1 JDK源码
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
- 逻辑概述:一个线程Thread0去执行aThreadLocal.set(…)时,首先会取出自己的ThreadLocalMap,如果该map不存在,则创建并存储(ThreadLocal对象,value)。如果map存在,则直接存储(ThreadLocal对象,value)。
- 对getMap(t)的解读见:“附录 1、ThreadLocal提供的set()、get()、remove()方法,都有一个getMap()方法。在这里补充说明下。”
2.1.1.1 重点关注:map.set(this, value); 实现原理
- 方法签名:
private void set(ThreadLocal<?> key, Object value) {
......
}
不贴完整源码了,毕竟在csdn上看源码并不是一个明智的决定~
对着IDEA上的源码,看本篇文章,才是不错的选择哟~
- 思想:既然map(ThreadLocalMap)的存储结构是Entry[] table; 那显然要在table中找到一个位置table[i],将<key, value>放进去。
- 如何查找呢?
(1)简单的办法:遍历table。很显然JDK的设计者没有采用这种低效的方式。
(2)哈希表的思路(学《数据结构与算法》的作用体现出来了!):对key求一个hash值,并将其转换为数组中的合法下标。
实践:index = hash(key) % capacity (index = hash(key) & (capacity - 1) )更高效
6.1.2 哈希表简单实现 有必要学一学的~
如何查找?(哈希表的思路)
- 回到set方法的源码:
Entry[] tab = table;
int len = tab.length;
int i = key.threadLocalHashCode & (len-1);
1)len是2的幂,
len - 1表示成2进制,就是1…1,那么x & 1…1的范围一定是[0, 1…1],也就是数组下标的合法范围。
2)len不是2的幂,x & (len - 1)的范围也是[0, len - 1]。因为,len - 1表示为二进制,与它相与,最大情况下,便是1都没变成0,那么就是len - 1。因此,范围也是[0, len - 1]
- 找到要放的位置了,但可能这个坑位已经被别人占了啊,这咋办?–> 遍历找下一个i。
for (Entry e = tab[i];
e != null;
e = tab[i = nextIndex(i, len)]) {
ThreadLocal
深入解析ThreadLocal:创建、API与内部存储结构详解

最低0.47元/天 解锁文章
689

被折叠的 条评论
为什么被折叠?



