ThreadLocal类

文件路径:
./libcore/ojluni/src/main/java/java/lang/ThreadLocal.java

ThreadLocal

概述:
提供线程本地变量. 此变量不同于一般变量,每个线程都访问(通过get和set)各自的副本.
独立初始化变量的副本. ThreadLocal实例是类的典型的私有静态域,是与线程状态相关的
(例如: 用户ID或事务ID)
每个线程持有一个Thread-Local变量的副本的隐式引用,只要线程存活和ThreadLocal可获取;
在线程消失后,thread-local实例被GC(除非还有其他的引用)
ThreadLocals依赖于附着在各个线程的hashmap.
ThreadLocal对象行为像键Key,通过threadLocalHashCode加快搜索.

 主要原理:
 每个线程有一个threadLocals成员变量(类型为ThreadLocal.ThreadLocalMap). 当使用到ThreadLocal时,此变量初始化(延时初始化).
 ThreadLocal.ThreadLocalMap为静态内部类,有成员变量table. table为 Entry数组,而Entry用来保存ThreadLocal键值对. 每set一个ThreadLocal键值对, table就添加一条Entry. remove则table移除一条Entry. 需要搜索时,用threadLocalHashCode辅助.
 当一个ThreadLocal对象在不同线程操作时,实际是在各自线程的ThreadLocalMap(threadLocals成员变量)的table上操作以此对象为key的Entry.

函数 说明
nextHashCode
initialValue 返回当前线程的初始化值,对这个thread-local变量. 此方法将在线程第一次通过get方法访问变量时被调用,除非线程先前调用了set方法,在这种情况下initialValue将不再被线程调用。一般情况下,此方法每个线程最多调用一次,但是在get后一旦子序列调用remove,可能再调用.
withInitial 创建一个thread local变量.变量的初始值由调用Supplier的get决定.
get 返回当前线程的这个thread-local变量的映射值. 如果变量没有当前线程的值,它第一次初始化的值是由initialValue方法的调用返回
setInitialValue set的变种,用来建立初始值.
set 设置当前线程的thread-local变量为指定值.
remove 移除当前线程的thread-local值
getMap 获得线程的ThreadLocalMap
createMap 创建与线程相关的ThreadLocalMap
createInheritedMap 工厂模式创建可继承的thread locals
childValue 当继承父类map时,子类获取的值

ThreadLocal.SuppliedThreadLocal

ThreadLocal的扩展,从指定的Supplier获取初始值

ThreadLocal.ThreadLocalMap

ThreadLocalMap自定义hash map,仅适应维护thread local值.
没有操作被输出到ThreadLocal外.为了帮助处理大的和长生命周期的使用,
hash table对key使用了WeakReferences. 然而,由于参考队列没有使用,
获得的旧的entries被移除仅当table运行超出作用域.

静态内部类
定义
INITIAL_CAPACITY 初始化Entry表的容量,必须是2的指数倍
table table.length必须是2的指数倍,必要时改变大小
size table中的entries数
threshold 当达到值时需要改变大小

函数
ThreadLocalMap(ThreadLocal,Object) :
构建一个新的Map初始值包含(firstKey,firstValue).ThreadLocalMap是延时构建,所以仅当有需要
放入(put)时才构建

ThreadLocalMap(ThreadLocalMap):
构建map从给定的父map中继承ThreadLocals; 仅被createInheritedMap调用; 子类继承的值可能不同,见childValue

getEntry:
查询key对应的Entry; 直接比对hashcode对应的,如果不匹配,再全搜索匹配,因为可能重排过

getEntryAfterMiss:
全搜索查询,直至查询完

setThreshold:
设置限值为参数的2/3

set:
设置与key相关的值; 如果对应的table不为空,则向后移; 清除无用的,调整大小

remove:
移除键的Entry

replaceStaleEntry:
交换slot的键值,可能做一些清除操作

expungeStaleEntry:
清除staleSlot,并可能重hash

nextIndex:
以len为模增加i

prevIndex:
以len为模减小i

cleanSomeSlots:
启动扫描一些单元查询旧的条目(entries). 这在一个新的元素添加或一个旧元素清除时.
它执行一个逻辑算法的扫描,为了平衡完全不扫描(快速但是保留了垃圾)和与元素成
比例的扫描次数(这将搜索出所有的垃圾,但可能花费O(n)的时间)之间的平衡.
i: 已知的不是旧元素的位置,从此后开始扫描
n: 扫描控制; log2(n)个单元将被扫描,除非有一个旧条目(entry)被找到,这样log2(table.length-1)
个额外单元被扫描. 当插入时,此参数是元素数量,但是当从replaceStaleEntry调用时,它是table长度
(注意:所有这些将被改变为n的权重,替换log n.但是这个版本更简单,快速,并且看起来工作良好)

rehash:
首先移除旧的条目. 如果条件满足,重新调整大小.

resize:
将大小翻倍,并重排

expungeStaleEntries:
清除表中所有旧的条目

ThreadLocal.ThreadLocalMap.Entry

此hash map继承于WeakReference,使用它的主引用域作为key(将一直是ThreadLocal对象),
注意null键表示没有引用,因此entry可以被删除

小结:

每个线程对应一个ThreadLocalMap
Thread <—对应—> ThreadLocal.ThreadLocalMap
每个ThreadLocalMap中包含一个Entry数组
Entry数组中每一项存储一个ThreadLocal键值对< ThreadLocal, Value >
一个ThreadLocal对象对应一个值

你可能感兴趣的:(JAVA,Android)