#Thread Local使用说明
- class ThreadLocal ThreadLocal 对象为每个线程保存了一个T 类型的副本。 当某些数据是以线程为作用域,并且不同线程具有不同副本的时候,就可以考虑采用ThreadLocal。 比如Handler 需要获取当前线程的Looper ,Looper 的作用域是线程且每个线程具有各自唯一的Looper 。 So Looper 使用的是ThreadLocal 保存Looper 对象。
- 在jdk 和SDK 中 Thread 和ThreadLocal 的代码是不同的。
#实现方案猜测
- 实现一,在ThreadLocal 内部 创建一个HashMap ,键为Thread 对象, 值为对应的T 对象。
- 实现二,在Thread 类创建一个HashMap ,键为ThreadLocal 对象,值为对应的T 对象
###方案分析:如果有5个ThreadLocal 对象,两个线程。 - 实现一,那么就要创建5个HashMap 。
- 实现二,创建2个HashMap。
So ,实现二要好的多,事实上JDK 和Android SDK 的ThreadLocal实现都是采用实现二。
在Thread 内部声明一个数据结构成员用于保存 ThreadLocal 对象 和Value ,只不过实现细节不同。
#JDK 的ThreadLocal 的代码细节
Thread 类内部声明了一个 threadLocals 成员变量。这是一个在ThreadLocal 的内部类。
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
这个ThreadLocal.ThreadLocalMap 定义如下: 可以看到使用弱引用来保存键值对。
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
#SDK 的实现方式
SDK的Thread 和JDK 的Thread 也是不同的。
/**
* Normal thread local values.
*/
ThreadLocal.Values localValues;
ThreadLocal.Values 类如下: 使用数组来保存键值对(1,3,5 位置是key 2,4,6 位置存值 )
/**
* Per-thread map of ThreadLocal instances to values.
*/
static class Values {
/**
* Size must always be a power of 2.
*/
private static final int INITIAL_SIZE = 16;
/**
* Placeholder for deleted entries.
*/
private static final Object TOMBSTONE = new Object();
/**
* Map entries. Contains alternating keys (ThreadLocal) and values.
* The length is always a power of 2.
*/
private Object[] table;
#后话
SDk ThreadLocal 的实现细节还是很复杂的。想了解可以参考如下连接: