前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅谈ThreadLocal

浅谈ThreadLocal

作者头像
你的益达
发布2020-08-14 09:35:28
2540
发布2020-08-14 09:35:28
举报

ThreadLocal介绍

ThreadLocal顾名思义,线程本地,即各个线程互不干扰的空间,每个线程只能看到当前线程放入的对象。

如下以泛型类型为String的类型为例,分析其内部结构图。

代码语言:javascript
复制
ThreadLocal<String> tl = new ThreadLocal<>();
tl.set("hellowThread");

有上图可以看出,放入ThreadLocal容器中的元素其实是放到该线程的成员变量threadlocals中的,其本质是一个Map,key存的是当前ThreadLocal对象,value存的是真实的对象。

代码语言:javascript
复制
public class ThreadLocal<T> {
    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();
    }


    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 getMap(Thread t) {
        return t.threadLocals;
     }
  }

从上述set()方法和get()方法中都可以看出,都是先获取到Thread对象中的ThreadLocalMap对象,然后对map进行操作的。如此每个线程只能拿到当前线程的成员变量map,因此肯定可以保证线程间互不干扰。

ThreadLocal弱引用问题

弱引用:只要遭遇gc,就回收该引用指向的区域。

代码语言:javascript
复制
    static class ThreadLocalMap {
        static class Entry extends WeakReference<ThreadLocal<?>> {
            /** The value associated with this ThreadLocal. */
            Object value;
            Entry(ThreadLocal<?> k, Object v) {
                super(k);
                value = v;
            }
        }
    }

ThreadLocalMap中的Entry是继承自 WeakReference,也就是说Entry对象中指向ThreadLocal对象的引用是一个弱引用。

这样做的目的是当tl被回收后,使得ThreadLocal对象自动被gc回收,避免内存泄漏。

假设Entry中的key指向ThreadLocal对象的引用是一个强引用,当前线程执行完后会回收其局部变量tl(例如tl = null),此时已经无法访问到该ThreadLocal对象了,但是由于强引用的存在,jvm觉得该ThreadLocal对象不是一个垃圾,因此不会回收,如此会引起内存泄漏问题。使用弱引用时就可以避免该问题,只要强引用tl一断,下次gc就可以回收ThreadLocal这部分内存。

此时还是存在内存泄漏问题,还是接着上述结构,ThreadLocal对象已经被回收了,此时的key为null,因此对于threadlocals中该key所对应的那个value永远就访问不到了,但是由于value强引用的存在,“hellowThread”所占的这部分内存还是得不到回收,因此还是会产生内存泄漏问题。对于该问题的解决方法为用完Threadlocal之后,应该执行其的remove()方法。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-08-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ThreadLocal介绍
  • ThreadLocal弱引用问题
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档