/** * Construct a new map initially containing (firstKey, firstValue). * ThreadLocalMaps are constructed lazily, so we only create * one when we have at least one entry to put in it. */ ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) { table = new Entry[INITIAL_CAPACITY]; int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1); table = new Entry(firstKey, firstValue); size = 1; setThreshold(INITIAL_CAPACITY); } 1.创建了一个Entry数组,初始化大小为16。
// We don't use a fast path as with get() because it is at // least as common to use set() to create new entries as // it is to replace existing ones, in which case, a fast // path would fail more often than not.
Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1);
for (Entry e = tab; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = e.get();
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(); } get方法体前两行和set方法一样,接下来分2种情况:
1.map为空,直接调用setInitialValue方法
private T setInitialValue() { T value = initialValue(); Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); return value; } setInitialValue方法体第一行调用initialValue方法(如下面代码所示),这个方法直接返回null赋值给value;接下来还是获取map,此时map是为空的,所以调用creatMap方法创建新的ThreadLocalMap对象。最后直接返回null。
protected T initialValue() { return null; } 2.map不为空,通过map调用getEntry方法,传入的参数是当前ThreadLocal对象,getEntry方法如下:
private Entry getEntry(ThreadLocal<?> key) { int i = key.threadLocalHashCode & (table.length - 1); Entry e = table; if (e != null && e.get() == key) return e; else return getEntryAfterMiss(key, i, e); } 首先通过keyhash计算获取数组下标再拿到Entry元素e,判断e不等于null而且e元素的key等于当前传入的ThreadLocal对象,直接返回e;否则执行getEntryAfterMiss方法:
private Entry getEntryAfterMiss(ThreadLocal<?> key, int i, Entry e) { Entry[] tab = table; int len = tab.length;
while (e != null) { ThreadLocal<?> k = e.get(); if (k == key) return e; if (k == null) expungeStaleEntry(i); else i = nextIndex(i, len); e = tab; } return null; } 这个getEntryAfterMiss方法个人认为做了三件事:
1.通过while循环解决hash冲突
2.判断是否有陈旧元素,有的话将其删除
3.拿到最终元素e返回
最后,get方法拿到元素e后,调用e.value获取value值返回。至此,get方法分析结束
3.3remove方法 先上源码:
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); } 相当于执行ThreadLocalMap的remove方法:
/** * Remove the entry for key. */ private void remove(ThreadLocal<?> key) { Entry[] tab = table; int len = tab.length; int i = key.threadLocalHashCode & (len-1); for (Entry e = tab; e != null; e = tab[i = nextIndex(i, len)]) { if (e.get() == key) { e.clear(); expungeStaleEntry(i); return; } } } for循环是为了解决hash冲突,解决hash冲突就是将i+1,如果e元素的key等于当前传入的ThreadLocal对象,那么就清空这个元素。结束