简析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. Jmeter中cookie自动存储

    1,新建一个测试计划,然后添加一个"HTTP Cookie 管理器"(用来存储cookie)2,新建一个线程组,添加一个Sampler-->“HTTP 请求”(用来登录用的) ...

  2. wordpress 修改默认分页条数

    哎,终于快做完了,今天弄了弄分页,真是网上扒的模板太高级了,把分页和导航的css和js冲突了,终于解决了, 然后有一个模板是三和一排显示的,其他的是单挑显示的,它默认10条,我寻思改成9条,找了半天, ...

  3. 获得APP的包名package和activity

    方法一: Aapt dumpbadging xxxx.apk(包的路径) 第一个框为包名 第二个框为主Activity名 方法二: 如果你装了Appium 可以这么操作下 进入设置页,选择APK  路 ...

  4. 分别用shell编程和c编程实现文件和目录的复制

    c编程参考:https://blog.csdn.net/maizi_hsx/article/details/78645698 makefile文件: copy:cp.o gcc cp.o -o cop ...

  5. 【转】Docker网络模式--默认模式bridge模式

    一 引言 当 Docker 启动时,会自动在主机上创建一个名为 docker0 虚拟网桥,这实际上就是 Linux 的一个 bridge,可以理解为一个软件交换机.它会在挂载到它的网口之间进行转发.系 ...

  6. 基于SILVACO ATLAS的a-IGZO薄膜晶体管二维器件仿真(05)

    关于特性曲线的输出调整: 初代版本 material material=igzo eg300=3.5 nc300=8.5e21 nv300=8.5e21 taun0=1e-9 taup0=1e-9 a ...

  7. oracle错误代码大全(超详细)

    本篇文章是对oracle错误代码进行了详细的总结与分析,需要的朋友参考下 ORA-00001: 违反唯一约束条件 (.)ORA-00017: 请求会话以设置跟踪事件ORA-00018: 超出最大会话数 ...

  8. 纯CSS实现吸顶效果

    position的属性有哪些? {  position: static;  position: relative;  position: absolute;  position: fixed; pos ...

  9. SQL Server 2014数据库开启远程连接(Windows Server 2016)

    1.打开SQL SERVER 配置管理器 2. 设置防火墙的入站规则 3.使用Navicat Premium连接SQL Server 

  10. python爬取course课程的信息

    目录 1.大模块页面 2.每个大模块中小模块的简单信息 3.每个小课程的详细信息 4.爬取所有评论 @   这几天爬取了course动态网页的课程信息,有关数据分析,机器学习,还有概率论和数理统计课程 ...