ThreadLocal部分源码解析
Posted rotk2015
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ThreadLocal部分源码解析相关的知识,希望对你有一定的参考价值。
-
线程局部变量提供类,ThreadLocal< T >,简单说,对于某个变量(对象),为每个线程维护一个自己的独立副本,实现线程隔离。
-
ThreadLocal定义了内部静态类ThreadLocalMap,而Thread类内维护了一个ThreadLocalMap类型的成员变量:threadLocals。
/* ThreadLocal values pertaining to this thread. This map is maintained * by the ThreadLocal class. */ ThreadLocal.ThreadLocalMap threadLocals = null;
-
内部类复习:实例化非静态内部类,必须先实例化外部类,非静态内部类可访问外部类的成员;而静态内部类,不可访问内部类资源,且可以直接实例化。简单来讲,静态内部类仅仅是处于外部类内而已。另:静态内部类可以有多个实例(个人理解,静态内部类的定义代码类似于静态方法,确实只有一份,但它的实例是不受静态约束的)。
-
那么,可以得出如下结论:每个Thread类对象持有一个独立的ThreadLocalMap对象,而ThreadLocal类,仅仅是一个操作ThreadLocalMap的工具类,每一个ThreadLocal对象,都对应操作某种线程局部变量对象。
-
对于ThreadLocal变量推荐用static修饰。(个人猜想原因是:一个ThreadLocal实例已经能对多线程内的ThreadLocalMap进行某种局部变量的“多操”,即 一个对一种 )
-
ThreadLocalMap类似于一个简单的HashMap,不过是用Entry数组实现的。 Entry 是其静态内部类:
/** * 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; } }
Entry内部维护了成员变量value,并且,Entry作为弱引用类型,指向了一个ThreadLocal对象。
-
ThreadLocal.get()原理:先定位当前线程Thread,获取对应的ThreadLocalMap,之后,以当前的ThreadLocal的引用(this)为索引,在ThreadLocalMap中找对应Entry,获取对应value。
public T get() { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) { ThreadLocalMap.Entry e = map.getEntry(this); if (e != null) { @SuppressWarnings("unchecked") T result = (T)e.value; return result; } } return setInitialValue(); }
-
ThreadLocal.ThreadLocalMap.getEntry():
private Entry getEntry(ThreadLocal<?> key) { int i = key.threadLocalHashCode & (table.length - 1); Entry e = table[i]; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e); }
其中,e.get()返回的正是当前的ThreadLocal对象。
参考:
以上是关于ThreadLocal部分源码解析的主要内容,如果未能解决你的问题,请参考以下文章