本文转载自微信公众号「三不猴子」,作者sanbuhouzi。转载本文请联系三不猴子公众号。
成都创新互联公司专注为客户提供全方位的互联网综合服务,包含不限于成都网站设计、成都做网站、外贸网站建设、禹会网络推广、微信小程序、禹会网络营销、禹会企业策划、禹会品牌公关、搜索引擎seo、人物专访、企业宣传片、企业代运营等,从售前售中售后,我们都将竭诚为您服务,您的肯定,是我们最大的嘉奖;成都创新互联公司为所有大学生创业者提供禹会建站搭建服务,24小时服务热线:13518219792,官方网址:www.cdcxhl.com
ThreadLocal是什么?
官方解释为:
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable.
我们通常创建的变量可以被任何线程访问和修改,而是用ThreadLocal创建的变量只能通过当前线程去访问和修改。
ThreadLocal原理
jdk版本1.8,我们先看一下ThreadLocal的源码,先从set方法开始。
- /**
- * Sets the current thread's copy of this thread-local variable
- * to the specified value. Most subclasses will have no need to
- * override this method, relying solely on the {@link #initialValue}
- * method to set the values of thread-locals.
- *
- * @param value the value to be stored in the current thread's copy of
- * this thread-local.
- */
- public void set(T value) {
- Thread t = Thread.currentThread();
- ThreadLocalMap map = getMap(t);
- if (map != null)
- map.set(this, value);
- else
- createMap(t, value);
- }
这个ThreadLocalMap是ThreadLocal的一个内部类,key是当前Thread对象,value是我们要存的对象。首先拿到当前线程对象,然后获取了个map,然后往这个map中放了当前ThreadLocal对象,如果map为空则创建一个map。看看getMap的逻辑。
- /**
- * Get the map associated with a ThreadLocal. Overridden in
- * InheritableThreadLocal.
- *
- * @param t the current thread
- * @return the map
- */
- ThreadLocalMap getMap(Thread t) {
- return t.threadLocals;
- }
getMap就是在Thread成员变量中获取一个map。往下就是ThreadLocalMap.set()看看set的逻辑。
- /**
- * Set the value associated with key.
- *
- * @param key the thread local object
- * @param value the value to be set
- */
- private void set(ThreadLocal> key, Object value) {
- // 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[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();
- }
这里构造了个Entry对象,这个Entry可以看成是map的一行数据,一个key-value对。再看看Entry的源码。
- static class Entry extends WeakReference
> { - /** The value associated with this ThreadLocal. */
- Object value;
- Entry(ThreadLocal> k, Object v) {
- super(k);
- value = v;
- }
- }
这个Entry对象竟然是继承了WeakReference对象。上面的流程用图画出来就是这样的。
总结起来就是:
ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value。
什么是弱引用呢? 为什么ThreadLocal要使用弱引用呢?
官方文档解释为:
- /**
- * Weak reference objects, which do not prevent their referents from being
- * made finalizable, finalized, and then reclaimed. Weak references are most
- * often used to implement canonicalizing mappings.
- *
- *
Suppose that the garbage collector determines at a certain point in time
- * that an object is weakly
- * reachable. At that time it will atomically clear all weak references to
- * that object and all weak references to any other weakly-reachable objects
- * from which that object is reachable through a chain of strong and soft
- * references. At the same time it will declare all of the formerly
- * weakly-reachable objects to be finalizable. At the same time or at some
- * later time it will enqueue those newly-cleared weak references that are
- * registered with reference queues.
- *
- * @author Mark Reinhold
- * @since 1.2
- */
就是不会被程序计数器计数的引用,所以在垃圾回收器回收的时候不管是否有引用都会被回收。由于垃圾回收器是一个优先级很低的线程,因此不一定会很快发现那些只具有弱引用的对象。
ThreadLocal为什么要使用弱引用?
因为当我们存入的对象被置为null的时候,也就是ThreadLocalMap的value为null,ThreadLocalMap的key是弱引用此时在下一次垃圾回收器回收垃圾的时候就可以回收掉这个key-value也是就一个Entry对象了。
既然弱引用是有助于垃圾回收的,那为什么ThreadLocal还是容易导致内存泄漏?
弱引用确实是有助于垃圾回收,但是也是有弊端的,假设我们现在存入了一个对象,此时虚拟机gc,将key弱引用回收,但是value依然是强引用,key被回收了,这个value无法通过通过ThreadLocal对象的get方法获取,它永远不会被访问到了,所以存在内存泄漏的风险。
如何避免内存泄漏
本文名称:为什么ThreadLocal容易导致内存泄漏?
文章出自:http://www.shufengxianlan.com/qtweb/news44/39744.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联