- FastThreadLocal
- Recycler
FastThreadLocal
FastThreadLocal的使用
示例代码
1 | private static FastThreadLocal<Object> threadLocal0 = new FastThreadLocal<Object>() { |
与ThreadLocal
相同,就算Thread中获取了同一个object
,两个线程对这个object
的更变都不会相互影响
示例的运行结果:
1 | java.lang.Object@7b21370 |
也就说两个线程拿到的Object
的内存地址不相同
把示例程序改为以下,判断两个线程是否会相互影响:
1 | public static void main(String[] args) { |
运行结果如下
1 | java.lang.Object@4ce83a23 |
也就是说Thread1不管如何去修改,Thread2拿到的永远和它最初拿到的那个对象相等
FastThreadLocal实现机制
- FastThreadLocal的创建
- FastThreadLocal的get()方法实现
- FastThreadLocal的set()方法实现
FastThreadLocal的创建
看FastThreadLocal
的构造方法
1 | private final int index; |
FastThreadLocal示例间的index
值独立,值为0,1,2,3…,如下:
1 | //io.netty.util.internal.InternalThreadLocalMap#nextVariableIndex |
也就是说每个FastThreadLocal
都有一个唯一的Index
,当做是身份标示
FastThreadLocal的get()方法实现
步骤:
- 获取ThreadLocalMap
通过之前的index获取 - 直接通过索引取出对象
- 初始化
如果还没初始化就初始化,只有首次调用get()
时会触发
1.获取ThreadLocalMap
1 | //io.netty.util.concurrent.FastThreadLocal#get() |
示例中的是普通的Thread,所以是用slowGet()
获取ThreadLocalMap
1 | //io.netty.util.internal.InternalThreadLocalMap#slowGet |
这个UnpaddedInternalThreadLocalMap.slowThreadLocalMap
实际上是JDK的ThreadLocal
.也就是说netty的InternalThreadLocalMap
实际上是基于JDK的ThreadLocal
实现
1 | static final ThreadLocal<InternalThreadLocalMap> slowThreadLocalMap = new ThreadLocal<InternalThreadLocalMap>(); |
之所以是slow
,是因为他需要通过ThreadLocal
去获取InternalThreadLocalMap
.
下面再看一下fastGet()
,也就是直接在FastThreadLocalThread
线程中使用时会调用的快速获取ThreadLocalMap的方式
1 | //io.netty.util.internal.InternalThreadLocalMap#fastGet |
FastThreadLocalThread
线程自己就维护了一个threadLocalMap
变量,通过这个就能拿到InternalThreadLocalMap
.
也就是说,普通的Thread是通过JDK的TreadLocal中维护<线程,InternalThreadLocalMap>
的键值对获取InternalThreadLocalMap
,而FastThreadLocalThread
中是自带InternalThreadLocalMap
2.直接通过索引取出对象
通过上一步获取到线程私有的InternalThreadLocalMap
后,又回到这一步:
1 | //io.netty.util.concurrent.FastThreadLocal#get() |
接下来会通过这个InternalThreadLocalMap
,取出对象:
1 | //io.netty.util.concurrent.FastThreadLocal#get(io.netty.util.internal.InternalThreadLocalMap) |
也就是说,首先获取这个线程私有的InternalThreadLocalMap
,然后通过当前FastThreadLocal对象的标示从InternalThreadLocalMap
获取这个FastThreadLocal对象对应的Object
此时我们会发现,所谓的InternalThreadLocalMap
,实际上是数组实现的
1 | //io.netty.util.internal.InternalThreadLocalMap#indexedVariable |
3.初始化
首次获取时值为UNSET,此时再调用客户端代码中的initialValue()
把new Object()放入ThreadLocalMap
FastThreadLocal的set()方法实现
- 获取ThreadLocalMap
基于数组实现的 - 直接通过索引set对象
- remove对象
如果是UNSET对象,调用remove方法
示例程序中的set()
会到下面这步
1 | //io.netty.util.concurrent.FastThreadLocal#set(V) |
获取到ThreadLocalMap
后set()
:
1 | //io.netty.util.concurrent.FastThreadLocal#set(io.netty.util.internal.InternalThreadLocalMap, V) |
简单看一下3.remove对象的remove(threadLocalMap)
:
1 | //io.netty.util.concurrent.FastThreadLocal#remove(io.netty.util.internal.InternalThreadLocalMap) |