Java后端技术全栈|快速掌握并发编程---深入学习ThreadLocal( 二 )


set方法整体为
Java后端技术全栈|快速掌握并发编程---深入学习ThreadLocal
文章图片
Java后端技术全栈|快速掌握并发编程---深入学习ThreadLocal
文章图片
Java后端技术全栈|快速掌握并发编程---深入学习ThreadLocal
文章图片
ThreadLocalMap构造方法
//这个属性是ThreadLocal的 , 就是获取hashcode(这列很有学问 , 但是我们的目的不是他)privatefinalintthreadLocalHashCode=nextHashCode();privateEntry[]table;privatestaticfinalintINITIAL_CAPACITY=16;//Entry是一个弱引用staticclassEntryextendsWeakReference<ThreadLocal<?>>{Objectvalue;Entry(ThreadLocal<?>k,Objectv){super(k);value=https://pcff.toutiao.jxnews.com.cn/p/20201102/v;}}ThreadLocalMap(ThreadLocalfirstKey,ObjectfirstValue){//数组默认大小为16table=newEntry[INITIAL_CAPACITY];//len为2的n次方 , 以ThreadLocal的计算的哈希值按照Entry[]取模(为了更好的散列)inti=firstKey.threadLocalHashCode&(INITIAL_CAPACITY-1);table[i]=newEntry(firstKey,firstValue);size=1;//设置阈值(扩容阈值)setThreshold(INITIAL_CAPACITY);}
然后我们看看map.set()方法中是如何处理的
privatevoidset(ThreadLocal<?>key,Objectvalue){Entry[]tab=table;intlen=tab.length;//len为2的n次方 , 以ThreadLocal的计算的哈希值按照Entry[]取模inti=key.threadLocalHashCode&(len-1);//找到ThreadLocal对应的存储的下标 , 如果当前槽内Entry不为空 , //即当前线程已经有ThreadLocal已经使用过Entry[i]for(Entrye=tab[i];e!=null;e=tab[i=nextIndex(i,len)]){ThreadLocal<?>k=e.get();//当前占据该槽的就是当前的ThreadLocal,更新value结束if(k==key){e.value=https://pcff.toutiao.jxnews.com.cn/p/20201102/value;return;}//当前卡槽的弱引用可能会回收了 , key:nullvalue:xxxObject , //需清理Entry原来的value , 便于垃圾回收value , 且将新的value放在该槽里 , 结束if(k==null){replaceStaleEntry(key,value,i);return;}}//在这之前没有ThreadLocal使用Entry[i] , 并进行值存储tab[i]=newEntry(key,value);//累计Entry所占的个数intsz=++size;//清理key为null的Entry , 可能需要扩容 , 扩容长度为原来的2倍 , 并需要进行重新hashif(!cleanSomeSlots(i,sz)&&sz>=threshold){rehash();}}
从上面这个set方法 , 我们就大致可以把这三个进行一个关联了:
Thread、ThreadLocal、ThreadLocalMap 。
Java后端技术全栈|快速掌握并发编程---深入学习ThreadLocal
文章图片
get方法
Java后端技术全栈|快速掌握并发编程---深入学习ThreadLocal
文章图片
Java后端技术全栈|快速掌握并发编程---深入学习ThreadLocal
文章图片
remove方法
Java后端技术全栈|快速掌握并发编程---深入学习ThreadLocal
文章图片
expungeStaleEntry方法代码里有点大 , 所以这里就贴了出来 。
//删除陈旧entry的核心方法privateintexpungeStaleEntry(intstaleSlot){Entry[]tab=table;intlen=tab.length;tab[staleSlot].value=https://pcff.toutiao.jxnews.com.cn/p/20201102/null;//删除valuetab[staleSlot]=null;//删除entrysize--;//map的size自减//遍历指定删除节点 , 所有后续节点Entrye;inti;for(i=nextIndex(staleSlot,len);(e=tab[i])!=null;i=nextIndex(i,len)){ThreadLocalk=e.get();if(k==null){//key为null,执行删除操作e.value=null;tab[i]=null;size--;}else{//key不为null,重新计算下标inth=k.threadLocalHashCode&(len-1);if(h!=i){//如果不在同一个位置tab[i]=null;//把老位置的entry置null(删除)//从h开始往后遍历 , 一直到找到空为止 , 插入while(tab[h]!=null){h=nextIndex(h,len);}tab[h]=e;}}}returni;}


推荐阅读