惠东县住房和城乡规划建设局网站,软件开发培训机构怎么样,设计网站最重要的是要有良好的,wordpress调用用户昵称文章目录 ThreadLocal源码分析#xff1a;set方法get方法remove方法 ThreadLocal内存泄漏问题 ThreadLocal
ThreadLocal提供了线程局部变量#xff0c;每个线程都可以通过set和get方法来对这个变量进行操作#xff0c;但不会和其他线程的局部变量冲突#xff0c;实现了线程… 文章目录 ThreadLocal源码分析set方法get方法remove方法 ThreadLocal内存泄漏问题 ThreadLocal
ThreadLocal提供了线程局部变量每个线程都可以通过set和get方法来对这个变量进行操作但不会和其他线程的局部变量冲突实现了线程的数据隔离
源码分析
set方法
public void set(T value) {Thread t Thread.currentThread();//getMap就是为了获取当前线程的ThreadLocalMapThreadLocalMap map getMap(t);if (map ! null)//如果map存在就直接以这个ThreadLocal为键设置键和值map.set(this, value);else//否则就为他创建一个ThreadLocalMap并设置第一个键和值createMap(t, value);
}ThreadLocalMap getMap(Thread t) {return t.threadLocals;
}void createMap(Thread t, T firstValue) {t.threadLocals new ThreadLocalMap(this, firstValue);
}get方法
public T get() {Thread t Thread.currentThread();ThreadLocalMap map getMap(t);if (map ! null) {//如果当前线程的ThreadLocalMap存在就尝试获取对应键值对ThreadLocalMap.Entry e map.getEntry(this);if (e ! null) {SuppressWarnings(unchecked)T result (T)e.value;return result;}}//如果threadLocals不存在或者当前的ThreadLocal不存在于这个map中return setInitialValue();
}private T setInitialValue() {T value initialValue();Thread t Thread.currentThread();ThreadLocalMap map getMap(t);if (map ! null)//当前ThreadLocal不存在于map中就加上设置value为空map.set(this, value);else//如果map不存在就创建并设置键值createMap(t, value);return value;
}protected T initialValue() {return null;
}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();//将key为null的键值对清除掉get和set方法底层也有用到expungeStaleEntry(i);return;}}
}private static int nextIndex(int i, int len) {return ((i 1 len) ? i 1 : 0);
}总结
可以看出ThreadLocal中并不存储值只是作为一个key来让线程从ThreadLocalMap中获取value从而实现了线程之间的数据隔离
每个线程都维护着一个ThreadLocalMapThreadLocalMap是ThreadLocal的内部类ThreadLocal中的set实际上是向当前线程的ThreadLocalMap中设置值键为创建的ThreadLocal对象
ThreadLocal内存泄漏问题
内存泄漏程序中间动态分配了内存但在程序结束时没有释放这部分内存从而造成那部分内存不可用的情况
内存溢出要求分配的内存超过了系统能给的
ThreadLocal中作为map中的key使用而且ThreadLocalMap中的key是弱引用弱引用对象在gc时会被回收而ThreadLocalMap和Thread的生命周期一样长就会存在key为null的情况value访问不到从而引发内存泄漏。所以使用ThreadLocal时最后最好调用remove方法显式调用expungeStaleEntry方法手动删除key为null的value防止value的积累
ThreadLocal的get和set方法某些时候也会调用expungeStaleEntry方法但这是不及时的而且不一定每次都会执行