• ThreadLocal使用及原理


    一.简介及作用

        在一些场景中,我们希望一些变量只能被某个线程访问,对其他线程是隔离的,就需要用到ThreadLocal.

        ThreadLocal具有线程隔离性,用于解决多线程中相同变量的访问冲突问题.使每个线程读到的变量都是相独立的.线程内部变量仅相对于本线程而言可见.

    二.简单使用

    存储值,直接调用set()方法
    取值,直接调用get()方法.

     ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
            for (int i = 0; i < 5; i++) {
                String threadName = "Thread" + i;
                new Thread(() -> {
                    threadLocal.set(threadName);
                    System.out.println(threadName + "获取到值:" + threadLocal.get());
                    threadLocal.remove();
                }, threadName).start();
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    输出结果:
    在这里插入图片描述

    注意:针对同一个Thread,ThreadLocal 只能存储一个值,如下案例:
    在这里插入图片描述

    三.原理:

    1. 首先Thread有一个成员变量ThreadLocal.ThreadLocalMap,也就是每一个Thread都自身绑定了一个ThreadLocal.ThreadLocalMap.
      在这里插入图片描述

    2. 而ThreadLocal的静态内部类ThreadLocalMap,最主要的结构就是一个entry数组.
      在这里插入图片描述

    3. 在存储元素的时候,首先我们能根据当前thread获取到当前绑定的ThreadLocalMap,然后利用threadlocalMap中的threadLocalHashcode()方法计算出当前要存储的entry数组中的下标位置,key就是threadLocal对象,value就是要存的值,组成一个entry存进去.
      在这里插入图片描述

    4. 取元素的时候也是根据当前线程对象,拿到threadLocalMap,再根据this(threadLocal对象)计算hash值,找到下标,取值即可

    四.自问自答

    1. 存储的数据结构是什么样的
      thread.ThreadLocal.ThreadLocalMap–>[,]

      数组中的下标就是通过当前threadLocal对象hash得到的.

    2. 为什么要传一个数组呢?
      对每一个线程来说,可能要存储的与之相关联的变量不只一个,所以必然需要一个集合去存储这些值.

    3. 当发生Hash冲突的时候是怎样处理的?
      ThreadLocal里面就有一个数组,不像hashMap,是数组+链表的结构,那么当ThreadLocal发生hash冲突的时候就会用到线性探测法,简单来说就是当冲突的时候,依次查找列表中离冲突单元最近的空闲单元,并且把新的键插入这个空闲单元.

    4. 为什么要用线性探测法?
          ThreadLocal 往往存放的数据量不会特别大(而且key 是弱引用又会被垃圾回收,及时让数据量更小),这个时候开放地址法简单的结构会显得更省空间,同时数组的查询效率也是非常高,加上第一点的保障,冲突概率也低

      开方地址法的缺点是容易产生堆积,不适用于大规模的存储.
      链地址法:不存在堆积问题,冲突处理简单,适合大数据存储.

    5. 为什么要是一个entry数组呢,不是一个单泛型得数组,比如说String数组?
          其实终其原因,是因为其在hash冲突的时候使用了线性探测法,会依次往后寻找空位置去插入,
      那么当我们去取值的时候,发生hash冲突,就得往后依次遍历比较哪一个是和我们存进去得key相等,才进行返回

    今天的分享就到这里了,有问题可以在评论区留言,均会及时回复呀.
    我是bling,未来不会太差,只要我们不要太懒就行, 咱们下期见.
    在这里插入图片描述

  • 相关阅读:
    发布https网页?用cpolar轻松做到
    高等数学--微分方程的求解(sympy库)
    好用的天气预报API推荐
    常见面试题-Spring的aop和ioc如何实现?
    【技术积累】Linux中的命令行【理论篇】【八】
    solidworks导入stl保持为曲面且可编译的注意项
    LDA代码训练报错记录
    Python之字符串判断
    maven 包管理平台-01-maven 入门介绍 + Maven、Gradle、Ant、Ivy、Bazel 和 SBT 的详细对比表格
    零基础入门JavaWeb——Web基本概念
  • 原文地址:https://blog.csdn.net/wangliangluang/article/details/126576249