Android 线程本地变量<二> ThreadLocal Values源码解析
@(Android系统源码解析)[Android, ThreadLocal, Values]
声明:转载请注明出处,知识有限,如有错误,请多多交流指正!
注:基于Android 6.0(API 23)源码
ThreadLocal内部类Values是被设计用来保存线程的变量的一个类,它相当于一个容器,存储保存进来的变量
静态内部类Values类解析
1. Values的结构
主要原理是Values将数据存储在数组table(Object[] table)
中,那么键值对如何存放的呢?就是table被设计为下标为0,2,4…2n的位置存放key,而1,3,5…(2n +1 )的位置存放value。取数据的时候可以直接通过下标存取线程变量。
2. Values的内部实现
成员变量
- private static final Object TOMBSTONE
= new Object(); // 表示被删除的实体标记,移除变量时它是把对应的key的位置赋值为TOMBSTONE
- private static final int INITIAL_SIZE
= 16; //默认的初始化容量
- private Object[] table
; //保存变量的地方,长度必须是2的n次方的值
- private int mask
; //计算下标的掩码,它的值是table的长度-1
- private int size
; //存放进来的实体的数量
- private inttombstones
; //表示被删除的实体的数量
- private int maximumLoad
; //阈值,用来判断是否需要进行rehash
- private int clean
; //表示下一个要进行清理的位置点
Values的构造
Values() {
// 默认创建32个长度的容器table
initializeTable(INITIAL_SIZE);
this.size = 0;
this.tombstones = 0;
}
private void initializeTable(int capacity) {
// 通过capacity创建table容器
this.table = new Object[capacity * 2];
// 下标的掩码
this.mask = table.length - 1;
this.clean = 0;
// 2/3 最大负载因子
this.maximumLoad = capacity * 2 / 3;
}
Values的方法
- void put(ThreadLocal
void put(ThreadLocal<?> key, Object value) {
//清理了废弃的元素
cleanUp();
// Keep track of first tombstone. That's where we want to go back
// and add an entry if necessary.
int firstTombstone = -1;
// 通过key获取索引index
for (int index = key.hash & mask;; index = next(index)) {
// 通过索引获取TheadLocal
Object k = table[index];
// 如果TheadLocal是存在,直接返回
if (k == key.reference) {
// Replace existing entry.
table[index + 1] = value;
return;
}
if (k == null) {
// 找到firstTombstone这个索引值,然后赋值对应的key和value
if (firstTombstone == -1) {
// Fill in null slot.
table[index] = key.reference;
table[index + 1] = value;
size++;
return;
}
// Go back and replace first tombstone.
table[firstTombstone] = key.reference;
table[firstTombstone + 1] = value;
tombstones--;
size++;
return;
}
// Remember first tombstone.
if (firstTombstone == -1 && k == TOMBSTONE) {
firstTombstone = index;
}
}
}
- private void cleanUp()
private void cleanUp() {
if (rehash()) {
// If we rehashed, we needn't clean up (clean up happens as
// a side effect).
return;
}
if (size == 0) {
// No live entries == nothing to clean.
return;
}
// Clean log(table.length) entries picking up where we left off
// last time.
int index = clean;
Object[] table = this.table;
for (int counter = table.length; counter > 0; counter >>= 1,index = next(index)) {
Object k = table[index];
// 如果已经删除,则删除下一个
if (k == TOMBSTONE || k == null) {
continue; // on to next entry
}
// The table can only contain null, tombstones and references.
@SuppressWarnings("unchecked")
Reference<ThreadLocal<?>> reference= (Reference<ThreadLocal<?>>) k;
// 如果ThreadLocal已经不存在,则释放value数据
if (reference.get() == null) {
// This thread local was reclaimed by the garbage collector.
table[index] = TOMBSTONE; //已经被释放了
table[index + 1] = null;
tombstones++; //被删除的数量
size--;
}
}
// Point cursor to next index.
clean = index;
}
- void add(ThreadLocal
void add(ThreadLocal<?> key, Object value) {
for (int index = key.hash & mask;; index = next(index)) {
Object k = table[index];
if (k == null) {
// 把ThreadLocal对象(key)和对应的value放在连续的位置中
// table被设计为下标为0,2,4...2n的位置存放key,而1,3,5...(2n +1 )的位置存放value
table[index] = key.reference;
table[index + 1] = value;
return;
}
}
}
private boolean rehash()
数组肯定要扩容,就是当前正在使用的内存大于分配内存的1/2的时候进行数扩容void remove(ThreadLocal key)
用来释放内存,清除数据