在 Android 和 Java 中,ThreadLocal 的实现原理主要依赖于 ThreadLocalMap 类。以下是 ThreadLocal 的实现细节和原理:
1. ThreadLocal 类
ThreadLocal 是一个用于存储线程局部变量的类。它的关键方法包括 get、set 和 remove,这些方法在底层操作一个与当前线程相关联的 ThreadLocalMap 实例。
2. ThreadLocalMap 类
ThreadLocalMap 是 Thread 类的内部类,实际上是一个哈希表,用于存储每个线程的线程局部变量。它的结构和方法如下:
2.1 内部结构
- Entry 类:
ThreadLocalMap的内部类Entry是一个键值对的容器。键是ThreadLocal对象(使用弱引用),值是线程局部变量的值。
static class ThreadLocalMap {
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
private Entry[] table;
}
- table:
ThreadLocalMap使用一个Entry数组来存储键值对。
2.2 设置和获取值
- set 方法:通过计算
ThreadLocal对象的哈希码并将其映射到table数组中的索引位置,将值存储到Entry中。如果在该位置已经有Entry对象,并且其ThreadLocal键与当前的ThreadLocal相同,则更新值;否则,创建新的Entry对象。
void set(ThreadLocal<?> key, Object value) {
// 计算索引
int i = key.threadLocalHashCode & (table.length - 1);
// 遍历 table 中的 Entry
for (Entry e = table[i]; e != null; e = table[nextIndex(i, table.length)]) {
ThreadLocal<?> k = e.get();
if (k == key) {
e.value = value;
return;
}
if (k == null) {
replaceStaleEntry(key, value, i);
return;
}
}
// 如果没有找到对应的 Entry,则创建新的 Entry
table[i] = new Entry(key, value);
}
- get 方法:计算
ThreadLocal对象的哈希码并找到对应的Entry。如果找到匹配的Entry,则返回其值;否则,返回null。
Object get(ThreadLocal<?> key) {
int i = key.threadLocalHashCode & (table.length - 1);
for (Entry e = table[i]; e != null; e = table[nextIndex(i, table.length)]) {
ThreadLocal<?> k = e.get();
if (k == key) {
return e.value;
}
if (k == null) {
expungeStaleEntries();
}
}
return null;
}
2.3 内存管理
-
弱引用:
ThreadLocal的键(ThreadLocal对象)使用弱引用,确保当ThreadLocal对象不再被引用时,可以被垃圾回收,从而避免内存泄漏。 -
清理过时的条目:
ThreadLocalMap会定期清理已回收的ThreadLocal对象对应的Entry。在get方法中,如果发现键已为null,则会调用expungeStaleEntries方法来移除过时的条目。
3. ThreadLocal 的生命周期
- ThreadLocal 变量的创建:每个线程创建时会初始化一个
ThreadLocalMap对象来存储其线程局部变量。 - 线程结束:当线程结束时,其
ThreadLocalMap也会被垃圾回收。由于ThreadLocal的键是弱引用,当ThreadLocal对象不再被使用时,它也会被回收,从而避免内存泄漏。
总结
ThreadLocal 的实现原理主要依赖于 ThreadLocalMap,它使用 ThreadLocal 对象作为键,并通过弱引用来避免内存泄漏。每个线程都有自己的 ThreadLocalMap 实例,确保线程局部变量的隔离。ThreadLocal 提供了线程安全的方式来管理每个线程的独立数据,避免了线程间的同步问题。


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



