简析ThreadLocal原理及应用

原创: 东晨雨 JAVA万维猿圈 4月17日

ThreadLocal的源码加上注释不超过八百行,源码结构清晰,代码也比较简洁。ThreadLocal可以说是Java中解决多线程数据共享问题方案中的一股清流,该方案为每个线程分配一个独立的变量副本,各个线程之间的变量互不干扰。下面一起来看看吧:

预计阅读时间:5分钟

ThreadLocal的定义与理解

定义和特点:

ThreadLocal顾名思义可以理解为线程本地变量,ThreadLocal将变量的各个副本值保存在各个线程Thread,Thread对象实例采用ThreadLocalMap数据结构来存储副本值。每个线程往这个ThreadLocal中读写是线程隔离,一种将可变数据通过每个线程有自己的独立副本从而实现线程封闭的机制。

适用场景:

(1)  当很多线程需要多次使用同一个对象,并且需要该对象具有相同初始化值;

(2)  适用于资源共享但不需要维护状态的情况,也就是一个线程对资源的修改,不影响另一个线程的运行;

(3) 基于ThreadLocal实现线程安全是采用"空间换时间",synchronized顺序执行是"时间换取空间"。

ThreadLocal方法及使用示例:

ThreadLocal与其内部类ThreadLocalMap以及线程类Thread联系紧密,为了分析ThreadLocal类的工作原理,先介绍该类的所有方法(JDK 1.8):

该类的核心方法包括4个

(1) protected T initialValue()

(2) public T get()

  1. 先获取当前线程的thread对象,再获取thread对象的threadLocalMap对象,然后根据当前的threadLocal对象取得table数组对应下标的Entry对象;

  2. 如果Thread对象的ThreadLocalMap为空的话,就调用setInitialValue方法,该方法初始化map并且放入null ( initialValue的返回值为null ),可以通过覆盖该方法修改没有set时的初始值。

(3) public void set( T value)

  1. 先调用Thread类的静态方法获得当前线程的Thread对象,每个线程对应的Thread对象都有一个ThreadLocalMap对象的引用;

  2. 获得当前线程的ThreadLocalMap对象;

  3. 如果不为空就调用set方法,如果为空就调用createMap方法,传入参数为ThreadLocalMap为空的Thread对象和T类型的firstValue。

(4) public void remove()

  1. 先获取当前线程的Map对象;

  2. 调用Map的remove方法,删除entry。

ThreadLocal使用注意事项

1、ThreadLoca对象是一个弱引用

ThreadLocalMap中的节点Entry继承了WeakReference类,定义了一个类型为Object的value,用于存放塞到ThreadLocal里的值。如果这里使用普通的key-value形式来定义存储结构,实质上就会造成节点的生命周期与线程强绑定,只要线程没有销毁,那么节点在GC分析中一直处于可达状态,没办法被回收,而程序本身也无法判断是否可以清理节点。ThreadLocal对象是一个继承自WeakReference的弱引用,当把ThreadLocal的实例置为空以后,没有任何强引用指向ThreadLocal的实例,所以ThreadLocal的将会被GC回收。生命周期只存活到下次GC前,可降低内存泄漏的风险。

2、ThreadLocal与内存泄漏

ThreadLocal对象是具有弱引用特点,虽然在一定程度上降低了内存泄漏的风险,但是在有线程复用如线程池的场景中,一个线程的寿命很长,大对象长期不被回收影响系统运行效率与安全,那么就存在一条强引用链的关系一直存在:Thread --> ThreadLocalMap-->Entry-->Value,最终造成内存泄漏。

如何避免内存泄漏:

调用ThreadLocal的get()、set()方法时完成后再调用remove方法,将Entry节点和Map的引用关系移除,这样整个Entry对象在GC Roots分析后就变成不可达了,下次GC的时候就可以被回收。

3、哈希冲突怎么解决

ThreadLocalMap中解决哈希冲突的方式并非链表的方式,而是采用线性探测的方式,具体来说,就是简单的步长加1或减1,寻找下一个相邻的位置。

简析ThreadLocal原理及应用的更多相关文章

  1. Java Android 注解(Annotation) 及几个常用开源项目注解原理简析

    不少开源库(ButterKnife.Retrofit.ActiveAndroid等等)都用到了注解的方式来简化代码提高开发效率. 本文简单介绍下 Annotation 示例.概念及作用.分类.自定义. ...

  2. PHP的错误报错级别设置原理简析

    原理简析 摘录php.ini文件的默认配置(php5.4): ; Common Values: ; E_ALL (Show all errors, warnings and notices inclu ...

  3. Java Annotation 及几个常用开源项目注解原理简析

    PDF 版: Java Annotation.pdf, PPT 版:Java Annotation.pptx, Keynote 版:Java Annotation.key 一.Annotation 示 ...

  4. [转载] Thrift原理简析(JAVA)

    转载自http://shift-alt-ctrl.iteye.com/blog/1987416 Apache Thrift是一个跨语言的服务框架,本质上为RPC,同时具有序列化.发序列化机制:当我们开 ...

  5. SIFT特征原理简析(HELU版)

    SIFT(Scale-Invariant Feature Transform)是一种具有尺度不变性和光照不变性的特征描述子,也同时是一套特征提取的理论,首次由D. G. Lowe于2004年以< ...

  6. 简析hotjar录屏功能实现原理

    简析hotjar录屏功能实现原理 众所周知,hotjar中录屏功能是其重要的一个卖点,看着很牛X酷炫的样子,今天就简单的分析一下其可能实现(这里只根据其请求加上个人理解分析,并不代表hotjar中真实 ...

  7. 基于IdentityServer4的OIDC实现单点登录(SSO)原理简析

    写着前面 IdentityServer4的学习断断续续,兜兜转转,走了不少弯路,也花了不少时间.可能是因为没有阅读源码,也没有特别系统的学习资料,相关文章很多园子里的大佬都有涉及,有系列文章,比如: ...

  8. Spring系列.@EnableRedisHttpSession原理简析

    在集群系统中,经常会需要将Session进行共享.不然会出现这样一个问题:用户在系统A上登陆以后,假如后续的一些操作被负载均衡到系统B上面,系统B发现本机上没有这个用户的Session,会强制让用户重 ...

  9. ThreadLocal原理简单刨析

    ThreadLocal原理简单刨析 ThreadLocal实现了各个线程的数据隔离,要知道数据是如何隔离的,就要从源代码分析. ThreadLocal原理 需要提前说明的是:ThreadLocal只是 ...

随机推荐

  1. 阿里云服务器-2.使用putty连接

    1.下载PuTTY 进入官网 点击我跳转 点击here 看自己电脑是多少位选择下载 2.安装 一直点击下一步就行 这里可以选择也可以不选择,这会在创建桌面快捷文件 看图注意事项 这里也可以用密匙,先去 ...

  2. php从接口获取数据转成可以用的数组或其他(含转换编码)

    程序开发,时常会用到将接口的json数据转换成程序可以用的,因为今天看到一个比较好的程序,贴上来,以备随时查看: /** * 将对象转成数组,并按要求转换编码 * * @param array $ar ...

  3. Jmeter-ServerAgent

    You can specify the listening ports as arguments (0 disables listening), default is 4444:   $ ./star ...

  4. 迭代器,for循环本质,生成器,常用内置方法,面向过程编程

    一.迭代器 1.迭代:更新换代(重复)的过程,每次的迭代都必须基于上一次的结果 迭代器:迭代取值的工具 2.迭代器给你提供了一种不依赖于索引取值的方式 3.可以迭代取值的对象:字符串,列表,元组,字典 ...

  5. mysql练习(增删改查)char、int使用

    (4)char的存储方式是,对英文字符(ASCII)占用1个字节,对一个汉字占用两个字节:而varchar的存储方式是,对每个英文字符占用2个字节,汉字也占用2个字节,两者的存储数据都非unicode ...

  6. 《JavaScript高级程序设计》读书笔记(三)基本概念第六小节理解函数

    内容---语法---数据类型---流程控制语句 上一小节---理解函数 本小节 函数--使用function关键字声明,后跟一组参数以及函数体 function functionName(arg0, ...

  7. 学习JavaScript数据结构与算法---前端进阶系列

    学习建议 1.视频学习---认知 建议:在中国慕课上找"数据结构"相关的视频教程.中国大学MOOC 推荐清华大学.北京大学.浙江大学的教程,可先试看,然后根据自身的情况选择视频进行 ...

  8. maven项目pom继承关系

    <dependency>部分下添加<exclusions>标记 Dependencies:是可选依赖(Optional Dependencies) Exclusions:是依赖 ...

  9. iOS 根据域名查询 IP 地址

    在 iOS 开发中,如果需要知道网站的 IP 地址: #include <netdb.h> #include <arpa/inet.h> NSString *webSiteSt ...

  10. jxl读取设置过数据有效性的xls文件报错

    //在用jxl读入excel时,一直报如下错误: Warning: Cannot read drop down range Unrecognized token 43 Exception in thr ...