asp建设网站需要了解什么,建网站衡水哪家强?,wordpress留言,域名备案网站购买首先看下ThreadLocal的set()方法存数据的过程#xff0c;首先获取当前的线程中保持的ThreadLocalMap#xff0c;每个线程的ThreadLocalMap都是不一样的#xff0c;因此存储的值是不同的。 public void set(T value) {Thread t Thread.currentThread();ThreadLocalMap map …首先看下ThreadLocal的set()方法存数据的过程首先获取当前的线程中保持的ThreadLocalMap每个线程的ThreadLocalMap都是不一样的因此存储的值是不同的。 public void set(T value) {Thread t Thread.currentThread();ThreadLocalMap map getMap(t);if (map ! null) {map.set(this, value);} else {createMap(t, value);}}如果在一个线程中首次使用ThreadLocal保持数据则需要创建ThreadLocalMapThreadLocalMap中保存数据的实体是Entry保存数据的过程就是先计算这个ThreadLocal对象的hashcode根据hashcode计算在Entry数组中的位置然后将创建的Entry保存在这个位置。 void createMap(Thread t, T firstValue) {t.threadLocals new ThreadLocalMap(this, firstValue);}ThreadLocalMap(ThreadLocal? firstKey, Object firstValue) {table new Entry[INITIAL_CAPACITY];int i firstKey.threadLocalHashCode (INITIAL_CAPACITY - 1);table[i] new Entry(firstKey, firstValue);size 1;setThreshold(INITIAL_CAPACITY);}如果在第一次之后使用ThreadLocal的话则根据ThreadLocal计算hashcode再根据hashcode计算Entry数组的索引根据索引找到这个线程对应的Entry如果是当前线程使用的ThreadLocalif (k key)则将对象设置进来即写到存储数据的Entry中。 private void set(ThreadLocal? key, Object value) {Entry[] tab table;int len tab.length;int i key.threadLocalHashCode (len-1);for (Entry e tab[i];e ! null;e tab[i nextIndex(i, len)]) {ThreadLocal? k e.get();if (k key) {e.value value;return;}if (k null) {replaceStaleEntry(key, value, i);return;}}tab[i] new Entry(key, value);int sz size;if (!cleanSomeSlots(i, sz) sz threshold)rehash();}当通过get()方法获取数据时首先找到当前的线程对象获取线程对象内部的ThreadLocalMap然后根据ThreadLocal对象计算Entry的索引找到本线程存储数据的Entry获取Entry中的数据。 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();}private Entry getEntry(ThreadLocal? key) {int i key.threadLocalHashCode (table.length - 1);Entry e table[i];if (e ! null e.get() key)return e;elsereturn getEntryAfterMiss(key, i, e);}ThreadLocal内存泄漏的问题 可以看到Entry是指向ThreadLocal的弱引用弱引用不会阻止gc的垃圾回收如果这个ThreadLocal对象置为null指向ThreadLocal对象的弱引用不会阻止gc的垃圾回收此时ThreadLocal对象存在但是无法访问通过get()方法获取value时需要计算ThreadLocal对象的hashcode在ThreadLocal对象被回收的情况就无法计算hashcode也就无法访问这个value引用的对象造成内存泄漏了。 static class Entry extends WeakReferenceThreadLocal? {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal? k, Object v) {super(k);value v;}}解决方法
将ThreadLocal变量定义成private static这样就一直存在ThreadLocal的强引用可以通过ThreadLocal对象访问到保存的数据不会造成内存泄漏调用remove()方法清除内存 public void remove() {ThreadLocalMap m getMap(Thread.currentThread());if (m ! null) {m.remove(this);}}private void remove(ThreadLocal? key) {Entry[] tab table;int len tab.length;int i key.threadLocalHashCode (len-1);for (Entry e tab[i];e ! null;e tab[i nextIndex(i, len)]) {if (e.get() key) {e.clear();expungeStaleEntry(i);return;}}}