privatevoidset(ThreadLocal<?> key, Object value){ Entry[] tab = table; //其实它是把值放到了数组中 int len = tab.length; int i = key.threadLocalHashCode & (len-1); //根据ThreadLocal对象的hash值,计算到table中的位置 //拿到ThreadLocal对象中的Entry,如果ThreadLocal对象的Entry不存在,就会在i位置直接 new Entry() //如果位置i的不为空,而且key不等于entry,那就找下一个空位置,直到为空为止。 for (Entry e = tab[i]; e != null; e = tab[i = nextIndex(i, len)]) { ThreadLocal<?> k = e.get(); if (k == key) { // 如果值相等就刷新Entry中的value; e.value = value; return; }
tab[i] = new Entry(key, value); int sz = ++size; if (!cleanSomeSlots(i, sz) && sz >= threshold) rehash(); }
以下是get时的源码
1 2 3 4 5 6 7 8 9 10
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); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
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[i]; } returnnull; }
4. ThreadLocal 数据共享
1 2 3 4 5 6 7 8 9 10
privatestaticvoidtest()throws InterruptedException { final ThreadLocal threadLocal = new InheritableThreadLocal(); threadLocal.set("帅得一匹"); Thread t = new Thread(() -> { System.out.println(Thread.currentThread().getName() + " 输出 " + threadLocal.get()); }, "t1"); t.start(); t.join(); System.out.println(Thread.currentThread().getName() + " 输出 " + threadLocal.get()); }
在子线程中我是能够正常输出那一行,这也就是父子线程数据传递的
**5. ThreadLocal内存溢出问题 **
1 2 3 4 5 6 7 8 9
staticclassEntryextendsWeakReference<ThreadLocal<?>> { /** The value associated with this ThreadLocal. */ Object value;