<返回更多

FastThreadLocal 原理分析

2019-08-28    
加入收藏

本文基于Netty 4.1.39分析,作者才疏学浅,欢迎拍砖

FastThreadLocal 作用

FastThreadLocal 作用与JDK 原生的ThreadLocal功能是一样的,FastThreadLocal 持有指定类的对象,可以保证每个线程都持有一个唯一实例,每个线程持有实例都只在本线程内使用,所以不会有并发问题。但它的访问速度更快,顾名思义FastThreadLocal。

FastThreadLocal 使用例子

我们现在想使每个线程都持有一个MySQL数据库连接实例。假设MySQLClient 就是数据库连接类。如下代码所示:

FastThreadLocal 原理分析

 

但是只实例化FastThreadLocal是不够的,这样运行最终还是会回退到JDK中的ThreadLocal。FastThreadLocal必须配合FastThreadLocalThread使用。也就是说FastThreadLocal 必须运行在FastThreadLocalThread 线程中才会生效,否则回退到ThreadLocal模式。这样就生效了,如图:

FastThreadLocal 原理分析

 

FastThreadLocal 实现原理

FastThreadLocalThread 维护了一个InternalThreadLocalMap变量 。如图所示:

FastThreadLocal 原理分析

 

InternalThreadLocalMap 使用数组实现存储 FastThreadLocal对象和其持有的实例。数组的下标就是FastThreadLocal 的index值,对应元素就是其持有的实例。

FastThreadLocal 在初始化时,就生成了一个全局唯一递增的索引下标index。如果图所示:

FastThreadLocal 原理分析

 

对应上面的例子就是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 的元素。

FastThreadLocal 原理分析

 

第一次获取实例时肯定是空的,所以会调用initialValue方法,此方法也是我们在new FastThreadLocal时覆盖的方法。如果我们不覆盖该方法,我们可以调用set方法,改方法会自动保存到当前线程的ThreadLocalMap变量中,这样下次再获取时就有实例了。

FastThreadLocal 为什么比JDK ThreadLocal快?

FastThreadLocal在get值时,是直接通过自身的index,从InternalThreadLocaMap的数组中直接取取出数据。而ThreadLocal每次get 都要先计算数组的下标,多了一个计算的步骤,其实就这么简单。

总结

FastThreadLocal 必须配合FastThreadLocalThread使用,整个过程就是替换掉JDK ThreadLocalMap,实现无需每次都计算数组小标,从而更快。所有文字都可以简化一张图,如果所示

FastThreadLocal 原理分析

 


 
声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>