ThreadLocal源码注释:
此类提供线程局部变量。这些变量的不同之处在于,访问该变量时会访问独属于当前线程的局部变量表。ThreadLocal实例通常是希望将状态与线程关联的类中的私有静态字段(例如,用户ID或事务ID)。
只要线程是活的,并且ThreadLocal实例是可访问的,每个线程都持有对其线程局部变量副本的隐式引用;在线程消失后,线程本地实例的所有副本都将进行垃圾收集(除非存在对这些副本的其他引用)。
线程局部变量是应用层的逻辑划分。在系统层面,进程是内存分配的最小单位,线程无独立内存。
应用示例
示例1
public class HttpContextUtil {
private static final ThreadLocal<User> USER_THREAD_LOCAL = new ThreadLocal<>();
public static void setLoginUser(User user) {
USER_THREAD_LOCAL.set (user);
}
public static User getLoginUser() {
return USER_THREAD_LOCAL.get();
}
public static void remove() {
USER_THREAD_LOCAL.remove();
}
}
示例2
package android.os;
public final class Looper {
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
/**
* 将当前线程初始化为循环器。
*/
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
/**
* 返回与当前线程关联的Looper对象。如果调用线程与Looper没有关联,则返回null。
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
/**
* 返回与当前线程关联的消息队列。
* 这必须从运行Looper的线程调用,否则将抛出NullPointerException。
*/
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
}
set
将值存储到thread.threadLocals中。(thread.threadLocals可视作Map<ThreadLocal, Object>)
public class ThreadLocal<T> {
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //返回 t.threadLocals
if (map != null) {
map.set(this, value);
} else {
createMap(t, value); //t.threadLocals = new ThreadLocalMap(this, firstValu0e);
}
}
......
}
get
从thread.threadLocals中取出值。(thread.threadLocals可视作Map<ThreadLocal, Object>)
public class ThreadLocal<T> {
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t); //返回 t.threadLocals
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue(); //map.set(this, null);
}
}
remove
public class ThreadLocal<T> {
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null) {
m.remove(this);
}
}
}
ThreadLocalMap.Entry
entry对threadLocal是弱引用,对value是强引用。
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
总结
- 每个
Thread实例持有一个map,用来保存线程局部变量;(类似Map<ThreadLocal, Object>) -
ThreadLocal实例作为key使用,在调用过该threadLocal的线程存有对应的value,没调用过的线程没有。 -
Thread与ThreadLocal是多对多的关系(m-n)。