这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (2)

简介: 这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (2)

第三个例子:Dubbo 的 RpcContext。


RpcContext 这个对象里面维护了两个 InternalThreadLocal,分别是存放 local 和 server 的上下文。


也就是我们说的增强版的 ThreadLocal:


image.png


作为一个 Dubbo 应用,它既可能是发起请求的消费者,也可能是接收请求的提供者。


每一次发起或者收到 RPC 调用的时候,上下文信息都会发生变化。


比如说:A 调用 B,B 调用 C。这个时候 B 既是消费者也是提供者。


那么当 A 调用 B,B 还是没调用 C 之前,RpcContext 里面保存的是 A 调用 B 的上下文信息。


当 B 开始调用 C 了,说明 A 到 B 之前的调用已经完成了,那么之前的上下文信息就应该清除掉。


这时 RpcContext 里面保存的应该是 B 调用 C 的上下文信息。否则会出现上下文污染的情况。


而这个上下文信息里面的一部分就是通过InternalThreadLocal存放和传递的,是 ContextFilter 这个拦截器维护的。


ThreadLocal 在 Dubbo 里面的一个应用就是这样。


当然,还有很多很多其他的开源框架都使用了 ThreadLocal 。


可以说使用频率非常的高。


什么?你说你用的少?


那可不咋的,人家都给你封装好了,你当个黑盒,开箱即用。


其实你用了,只是你不知道而已。


强在哪里?


前面说了 ThreadLocal的几个应用场景,那么这个 InternalThreadLocal 到底比 ThreadLocal 强在什么地方呢?


先说结论。


答案其实就写在类的 javadoc 上:


image.png


InternalThreadLocal 是 ThreadLocal 的一个变种,当配合 InternalThread 使用时,具有比普通 Thread 更高的访问性能。


InternalThread 的内部使用的是数组,通过下标定位,非常的快。如果遇得扩容,直接数组扩大一倍,完事。


而 ThreadLocal 的内部使用的是 hashCode 去获取值,多了一步计算的过程,而且用 hashCode 必然会遇到 hash 冲突的场景,ThreadLocal 还得去解决 hash 冲突,如果遇到扩容,扩容之后还得 rehash ,这可不得慢吗?


数据结构都不一样了,这其实就是这两个类的本质区别,也是 InternalThread 的性能在 Dubbo 的这个场景中比 ThreadLocal 好的根本原因。


而 InternalThread 这个设计思想是从 Netty 的 FastThreadLocal 中学来的。


本文主要聊聊 InternalThread ,但是我希望的是大家能学到这个类的思想,而不是用法。


首先,我们先搞个测试类:


public class InternalThreadLocalTest {
    private static InternalThreadLocal<Integer> internalThreadLocal_0 = new InternalThreadLocal<>();
    public static void main(String[] args) {
        new InternalThread(() -> {
            for (int i = 0; i < 5; i++) {
                internalThreadLocal_0.set(i);
                Integer value = internalThreadLocal_0.get();
                System.out.println(Thread.currentThread().getName()+":"+value);
            }
        }, "internalThread_have_set").start();
        new InternalThread(() -> {
            for (int i = 0; i < 5; i++) {
                Integer value = internalThreadLocal_0.get();
                System.out.println(Thread.currentThread().getName()+":"+value);
            }
        }, "internalThread_no_set").start();
    }
}


上面代码的运行结果是这样的:


image.png


首先是判断了传进来的 value 是否是 null 或者是 UNSET,如果是则调用 remove 方法。


null 是好理解的。这个 UNSET 是个什么鬼?


根据 UNSET 能很容易的找到这个地方:


image.png


原来是 InternalThreadLocalMap 初始化的时候会填充 UNSET 对象。


所以,如果 set 的对象是 UNSET,我们可以认为是需要把当前位置上的值替换为 UNSET,也就是 remove 掉。


而且,我们还看到了两个关键的信息:


1.InternalThreadLocalMap 虽然名字叫做 Map ,但是它挂羊头卖狗肉,其实里面维护的是一个数组。


2.数组初始化大小是 32。


接着我们回去看 else 分支的逻辑:


image.png


调用的是 InternalThreadLocalMap 对象的 get 方法。


而这个方法里面的两个 get 就有趣了。


能走到 fastGet 方法的,说明当前线程是 InternalThread 类,直接可以获取到类里面的 InternalThreadLocalMap。


如果走到 slowGet 了,则回退到原生的 ThreadLocal ,只是在原生的里面,我还是放的 InternalThreadLocalMap:


image.png

目录
相关文章
|
Java
「Java面试」被这题怼到不行,什么是可重入锁能解决什么问题?
一位3年工作经验的小伙伴,去一家互联网公司面试,结果被面试官怼了。面试官说:”这么简单的问题你都不知道?没法聊了,回去等通知吧“。然后,回来跟我是一阵诉苦。
124 0
|
Java 应用服务中间件 Spring
ThreadLocal 的使用及踩坑
ThreadLocal 的使用及踩坑
117 1
|
存储 缓存 Java
终于弄明白了ThreadLocal
ThreadLocal是Thread的局部变量,用于编多线程程序,对解决多线程程序的并发问题有一定的启示作用。
165 0
终于弄明白了ThreadLocal
|
算法 安全 Java
threadlocal再温习
早时总结过《ThreadLocal解析》、《FastThreadLocal解析》 最近看一些资料的时候,又重重发现了这类,不希望再温下,许多知识点,之前已经总结了,这篇文章主要有两个问题: 1、弱引用的意义 2、如何防键冲突
251 0
threadlocal再温习
|
存储 安全 算法
面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(一)
在平时中集合使用中,当涉及多线程开发时,如果使用HashMap可能会导致死锁问题,使用HashTable效率又不高。而ConcurrentHashMap在保持同步同时并发效率比较高,ConcurrentHashmap是最好的选择,那面试中也会被常常问到,那可能的问题是:
428 0
面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(一)
|
存储 安全 算法
面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(二)
在上篇《面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(一)》,研究了基础原理,以及ConcurrentHashMap数据put的流程等线程安全的,来回顾一下面试的问题点
179 0
面试:为了进阿里,死磕了ConcurrentHashMap源码和面试题(二)
|
安全 Java 编译器
面试突击51:为什么单例一定要加 volatile?
面试突击51:为什么单例一定要加 volatile?
130 0
|
Java
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (3)
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (3)
84 0
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (3)
|
Dubbo Java 应用服务中间件
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (5)
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (5)
140 0
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (5)
|
XML Dubbo 安全
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (1)
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (1)
134 0
这玩意比ThreadLocal叼多了,吓得why哥赶紧分享出来。 (1)

热门文章

最新文章

下一篇
开通oss服务