本文基于Netty 4.1.39分析,作者才疏学浅,欢迎拍砖FastThreadLocal 作用FastThreadLocal 作用与JDK 原生的ThreadLocal功能是一样的,FastThreadLocal 持有指定类的对象,可以保证每个线程都持有一个唯一实例,每个线程持有实例都只在本线程内使用,所以不会有并发问题 。但它的访问速度更快,顾名思义FastThreadLocal 。
FastThreadLocal 使用例子我们现在想使每个线程都持有一个MySQL数据库连接实例 。假设MySQLClient 就是数据库连接类 。如下代码所示:
文章插图
但是只实例化FastThreadLocal是不够的,这样运行最终还是会回退到JDK中的ThreadLocal 。FastThreadLocal必须配合FastThreadLocalThread使用 。也就是说FastThreadLocal 必须运行在FastThreadLocalThread 线程中才会生效,否则回退到ThreadLocal模式 。这样就生效了,如图:
文章插图
FastThreadLocal 实现原理FastThreadLocalThread 维护了一个InternalThreadLocalMap变量。如图所示:
文章插图
InternalThreadLocalMap 使用数组实现存储 FastThreadLocal对象和其持有的实例 。数组的下标就是FastThreadLocal 的index值,对应元素就是其持有的实例 。
FastThreadLocal 在初始化时,就生成了一个全局唯一递增的索引下标index 。如果图所示:
文章插图
对应上面的例子就是MYSQL_CLIENT_HOLDER 初始化时生成了index值 ,index从1开始,所以第一次实例FastThreadLocal时,index=1,则存储在InternalThreadLocalMap 数组的元素的状是 :
indexedVariables[1] = MySQLClient 实例明白了FastThreadLocal ,FastThreadLocalThread,InternalThreadLocalMap的关系之后,MYSQL_CLIENT_HOLDER.get() 其内部实现的部署就很简单了 。
1,获取当前线程
2,获取当前线程的InternalThreadLocalMap变量 。
3,获取FastThreadLocal 实例MYSQL_CLIENT_HOLDER的index值 。
4,获取InternalThreadLocalMap 数组 indexedVariables 下标为 index 的元素 。
文章插图
第一次获取实例时肯定是空的,所以会调用initialValue方法,此方法也是我们在new FastThreadLocal时覆盖的方法 。如果我们不覆盖该方法,我们可以调用set方法,改方法会自动保存到当前线程的ThreadLocalMap变量中,这样下次再获取时就有实例了 。FastThreadLocal 为什么比JDK ThreadLocal快?FastThreadLocal在get值时,是直接通过自身的index,从InternalThreadLocaMap的数组中直接取取出数据 。而ThreadLocal每次get 都要先计算数组的下标,多了一个计算的步骤,其实就这么简单 。
总结【FastThreadLocal 原理分析】FastThreadLocal 必须配合FastThreadLocalThread使用,整个过程就是替换掉JDK ThreadLocalMap,实现无需每次都计算数组小标,从而更快 。所有文字都可以简化一张图,如果所示
文章插图
推荐阅读
- 淘宝发展现状分析 淘宝发展战略分析
- Java NIO的三种Reactor线程模型分析
- ELK交换机日志分析
- 汽车四冲程汽油发动机的工作原理是什么?
- Mysql死锁如何排查?insert on duplicate死锁排查过程分析
- 微服务API通过ip可访问,域名不可访问问题分析
- HR也适合的数据分析工具,更有福利赠送
- CC攻击原理与防护手段!
- 刷机会不会影响手机?一文读懂“刷机原理”,让你变成手机专家
- 深度分析:你手机的电量去哪儿了?