Java并发之ThreadLocal源码分析(第二篇:添加元素)

2023-11-13

前言

    两个与添加元素相关的方法,initialValue()用于初始化一个默认值,set()用于添加一个元素 

 

set()方法分析

 

    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
    }

用于添加一个元素的方法,传入的参数是需要保存的Value对象,即所谓的线程局部变量

1、获取当前线程

首先获取调用set()方法的当前Thread对象,并由局部变量t保存

2、获取当前线程持有的ThreadLocalMap对象

接着将当前Thread对象t传入到getMap()方法中,get()方法会返回一个ThreadLocalMap对象,ThreadLocalMap对象是一个哈希表结构的容器,每个Thread对象都会持有一个ThreadLocalMap对象,

3、检查是否成功获取到当前线程持有的ThreadLocalMap对象

getMap()方法有可能返回null,当返回null时,说明Thread对象负责持有的ThreadLocalMap对象还没有创建,所以这里对map进行了判断,分别对两种情况做了不同的业务逻辑

a、当map不等于null时,说明Thread持有的ThreadLocalMap对象已经创建,直接调用ThreadLocalMap对象的set()方法添加一个元素,传入的第一个参数是Key对象,第二个参数是Value对象,此处我们传入的Key对象是当前ThreadLocal对象,Value对象则是方法中传入的T类型的对象

b、当map为null空,则会调用一个createMap()方法用于创建ThreadLocalMap对象,createMap()方法接受的第1个参数是当前Thread对象(注意此处是线程对象,不是ThreadLocal对象),第2个参数是T类型的对象value(线程局部变量,即元素),createMap()方法创建负责缓存key-value对象的容器对象,即ThreadLocalMap对象,它的结构是哈希表,底层是数组,解决哈希冲突用了单链表,而我们添加进去的T类型的对象(元素),将作为该哈希表ThreadLocalMap对象的第一个Entry元素(key-value)中的value,其中的key就是当前ThreadLocal对象

 

initialValue()方法分析

    protected T initialValue() {
        return null;
    }

用于初始化一个默认Value值的方法,一般我们都会重写该方法,注意它是protected修饰

initialValue()方法的返回值就是我们要存储的线程局部变量对象(元素),第一次调用ThreadLocal的get()方法(第三篇:获取元素)的时,initialValue()方法会返回一个Value对象

 

getMap()方法分析

    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }

用于返回Thread对象持有的ThreadLocalMap对象,传入的参数是Thread对象,一般我们都会传入当前线程

返回的数据类型是ThreadLocalMap,ThreadLocalMap作为静态内部类位于ThreadLocal类中

 

Thread对象持有的threadLocals

    ThreadLocal.ThreadLocalMap threadLocals = null;

可以清楚的看到ThreadLocalMap是ThreadLocal中的一个静态内部类

 

createMap()方法分析

 

    void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

用于为Thread对象创建持有的ThreadLocalMap对象的方法,传入的第1个参数为Thread对象,传入的第2个参数为Value(第一次保存的线程局部变量)

 

 

总结

1、通过重写ThreadLocal的initialValue()方法,我们可以设置一个默认的线程局部变量对象,好处是,我们在创建ThreadLocal对象时,即保存了一个线程局部变量

2、第一次调用ThreadLocal对象的get()方法时(此时未通过set设置过线程局部变量对象),initialValue()方法返回的线程局部变量对象会存储在一个哈希表(ThreadLocalMap)中

3、通过ThreadLocal的set()方法我们可以添加一个以ThreadLocal对象为key,线程局部变量对象为value的元素到ThreadLocalMap对象中,因ThreadLocalMap对象由当前Thread对象持有,所以set()方法总是需要获得调用它的Thread对象,通过Thread.currentThread()即可得到当前线程对象(在Java虚拟机中,一个Thread对象会对应一个操作系统中的线程)

4、ThreadLocal能实现以Thread为作用域,存储一个对象,依靠的是每个Thread对象持有的一个ThreadLocalMap对象,具体的添加元素过程则是由ThreadLocalMap对象的set()方法完成的

5、当你通过ThreadLocal对象添加一个对象作为线程局部变量时,该对象的引用会存储在Thread对象持有的一个ThreadLocalMap对象中,再由ThreadLocalMap持有的数组对象负责持有

6、Thread对象持有的ThreadLocalMap对象是在ThreadLocal的createMap()方法中创建的!

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java并发之ThreadLocal源码分析(第二篇:添加元素) 的相关文章

  • “先裁掉女员工!”

    身为女性在职场 不得不面对一些尴尬的时刻 我朋友公司刚招了一个商务的妹纸 没几周就说自己怀孕了 紧接着 开启了三天打鱼两天晒网的请假模式 今年就业环境不太理想 朋友公司招人有严格的名额限制 考虑再三 上司和HR昨天找她面谈 上司说 市场岗压
  • leveldb 源码--总体架构分析

    一 本文目的 对leveldb的总体设计框架分析 关于leveldb基本原理 此文不做阐述 读者可以自行检索文章阅读即可 对leveldb中底层数据存储数据格式 内存数据模型 compact 版本管理 快照等机制实现介绍以及整个leveld
  • 弯道超车,阿里高工新产Java面试速成指南,面试骚操作都在里面了

    金三银四过去一半 市场火热 但是大家就业压力却没有缓解多少 很多粉丝后台留言 Java程序员面临的竞争太激烈了 我自己也有实感 多年身处一线互联网公司 虽没有直面过求职跳槽的残酷 但经常担任技术面试考官 对程序员招聘市场的现状很清楚 导致现
  • C++中.cpp和.hpp的区别

    时间 2020 06 02 标签 c cpp hpp 区别 栏目 C C 繁體版 原文 https my oschina net u 4398200 blog 3336507 原文地址 https blog csdn net qzx9059
  • H5中写一个下拉框,点击下拉框内容会出现在文本域中

    朋友出去面试做的面试题 分享了下 我就拿来做做 原题 HTML中有个下拉框 包含 风 雨 雷 电 添加事件 当选择风时 文本域内出现选择
  • 使用proteus仿真集成运放构成的三角波发生电路

    仿真电路图 仿真示波器结果
  • 用python做小游戏——以弹球游戏为例

    本博客使用了Pygame库来创建游戏窗口和处理游戏逻辑 一 代码详细解释 首先 通过调用pygame init 来初始化Pygame库 然后创建一个窗口并设置标题 pygame init screen pygame display set
  • 当全景视频遇到快手

    收到 山巅之处 正午的阳光透过翻滚的云海铺洒在岩石壁上 镶嵌在天边连绵起伏的山峦若隐若现 雄伟壮观 俯瞰去 脚下是天梯般陡峭的山崖 连接着山中绿洲 纵身一跃 映入眼帘的是逐渐清晰的林海 那些拔地而起的树木紧密相连 铸成一座郁郁葱葱的 绿色长
  • docker容器内服务访问宿主机服务

    我的个人博客 逐步前行STEP 本文背景 操作系统 macOs 笔者的docker虚拟机中运行了nginx node服务用来部署一个前后端分离的网站 但是由于docker内的node服务运行效率极低 每次代码更新后也不会自动重新编译 所以准
  • 函数间隔和几何间隔

    问题描述 求一个任意点 到一个超平面的距离 超平面表示 在线性代数中 一个超平面可以用下式表示 y X W T
  • 借助ChatGPT自动生成PPT

    借助ChatGPT自动生成PPT 首先让GPT生成一段markdown格式的PPT内容 尽量描述全面 以什么语言 什么格式 排版等等 打开mindshow网址 点击import and create 选择以markdown方式创建 再次点击
  • c++: 实战详解vector

    目的 本文从实际使用的角度出发 简介C 中vector的基本用法 如增 删 改 查等 并举例说明 增 如下代码演示如何向vector中添加元素 其中 include
  • NotePad++添加到右键快捷方式

    首先看效果图 NotePad 添加到右键快捷方式 接下来是操作方式 首先在桌面上新建一个txt文本文档 然后将写入如下内容 Windows Registry Editor Version 5 00 HKEY CLASSES ROOT she
  • 人才梯队如何搭建,3个维度让你打造一支人才团队

    模型在手 方法我有 文末完整版 一 人才梯队可以不建立吗 二 人才梯队建设的目的 三 梯队人才的培养模型 四 梯队人才的管理 五 人才梯队建设发展通道 人才盘点 素质模型 人才盘点的内容 人才盘点的结果 人才分类 人才选拔 晋升与发展 今日
  • hive中常见的谓词操作符/比较符号

    hive中
  • STM32F103移植FreeRTOS必须搞明白的系列知识---2(FreeRTOS任务优先级)

    STM32F103移植FreeRTOS必须搞明白的系列知识 1 Cortex CM3中断优先级 STM32F103移植FreeRTOS必须搞明白的系列知识 2 FreeRTOS任务优先级 STM32F103移植FreeRTOS必须搞明白的系
  • 一文带你了解芯片制造的6个关键步骤

    在智能手机等众多数码产品的更新迭代中 科技的改变悄然发生 苹果A15仿生芯片等尖端芯片正使得更多革新技术成为可能 这些芯片是如何被制造出来的 其中又有哪些关键步骤呢 智能手机 个人电脑 游戏机这类现代数码产品的强大性能已无需赘言 而这些强大
  • el-radio值无法回显

    首先检查 label 绑定一个动态变量 其次label为number类型可以直接回显 为string类型需要在最外层再加一层单引号
  • 【Android Socket专题】:UDP通信客户端app的demo的实现

    Android Socket 专题 UDP Client客户端 http blog csdn net shankezh article details 50731287 UDP Server服务器 http blog csdn net sh

随机推荐

  • Linux里隐藏的计算器,你知道它的奥秘吗?

    大家都知道 windows下有个计算器工具 我们在工作生活中经常使用到它 但是 你可知Linux下也同样有个计算器吗 当然 良许说的是命令行下的计算器工具 而不是界面型的计算器 良许是Linux应用开发工程师 平时基本是在命令行下工作 所以
  • MYSQL数据类型

    MySQL中定义数据字段的类型对你数据库的优化是非常重要的 MySQL支持多种类型 大致可以分为三类 数值 日期 时间和字符串 字符 类型 数值类型 MySQL支持所有标准SQL数值数据类型 这些类型包括严格数值数据类型 INTEGER S
  • 二. Gateway 网关基础使用示例与自定义全局过滤器

    目录 一 步骤 二 目标服务 三 创建 Gateway 网关服务 三 自定义 GatewayFilter 过滤器 四 通过自定义 GatewayFilter 过滤器实现允许跨域问题 一 步骤 需求 现在有一个服务需要使用 Gateway 网
  • L2 开始揭开钢琴的盖子

    L2 开始揭开钢琴的盖子 1 计算机打开电源时执行的第一条指令 通常是IP指针 或PC指针 指向的内容 由硬件设计者决定 以 x86 计算机为例 x86 PC 刚开机时 CPU处于 实模式 寻址方式为 CS IP 开机时 CS 0xFFFF
  • poj1240

    本题为已知M 叉树的前序遍历与后序遍历 要求给出对应树有多少种可能 与poj2255类似 只要划分出子树 就把问题规模缩小了 然后就可以递归 目前只会写递归 M叉树的前序遍历为 根 子树1 子树2 子树K K lt M M叉树的后序遍历为
  • Unity 解决视频放入unity 报错VideoClip import error/Could not find supported video track

    原因 编码格式不对 具体支持什么编码 不想去查 懒 解决方案 通过格式化工厂修改编码格式 步骤如下 1 下载安装格式化工厂 2 选择MP4 3 添加你要转换格式的视频 5 点击输出配置 更改视频编码如图所示 确定 6 点击开始转换 成功后点
  • ThreadLocal的学习

    ThreadLocal叫做线程变量 意思是ThreadLocal中填充的变量属于当前线程 该变量对其他线程而言是隔离的 也就是说该变量是当前线程独有的变量 ThreadLocal为变量在每个线程中都创建了一个副本 那么每个线程可以访问自己内
  • MVC在Web系统中的模式与应用

    摘要 面向对象的设计模式是经验的总结 MVC思想是原先用于构建用户界面的 这篇文章主要论述了如何在新的Web应用领域中使用设计模式和MVC架构 文章首先介绍了设计模式的概念和特点 以及MVC架构的设计思想 并分析了MVC架构中包含的几种主要
  • 基于对象语言

    所谓的基于对象语言 指的是在程序的内部已经为用户提供好若干个对象 用户直接使用这些对象即可 如 javascript
  • RSA算法的数论原理与实现

    RSA算法的数论原理与实现 RSA算法是一种常用的非对称加密算法 能够确保数据的安全性和完整性 其基本原理是利用大素数的乘积进行加密和解密操作 而且在目前的计算机领域中 RSA算法被广泛应用于各种网络通信和数据传输中 一 数论知识和原理 质
  • 电脑预览,电脑怎么预览psd格式?

    经常使用PS的朋友们都知道Photoshop文档的默认格式是psd格式 可是在电脑上可能不能像jpg图片一样显示缩略图预览 遇到这种情况我们该怎么办 要是电脑上并没有安装PS软件又该怎么预览 下面我们就一起来看看哪些解决方法 步骤如下 方法
  • Mysql中having语句与where语句的用法与区别

    分析 回答 我们在写sql语句的时候 经常会使用where语句 很少会用到having 其实在mysql中having子句也是设定条件的语句与where有相似之处但也有区别 having子句在查询过程中慢于聚合语句 sum min max
  • 网络安全——数据链路层安全协议

    作者简介 一名云计算网络运维人员 每天分享网络与运维的技术与干货 座右铭 低头赶路 敬事如仪 个人主页 网络豆的主页 目录 前言 一 数据链路层安全协议简介 1 数据链路安全性 二 局域网数据链路层协议 1 本地链路局域网 LAN 2 广域
  • 学习笔记:简谈推挽电路

    推挽电路 push pull 就是两个不同极性晶体管间连接的输出电路 推挽电路采用两个参数相同的功率BJT管或MOSFET管 以推挽方式存在于电路中 各负责正负半周的波形放大任务 电路工作时 两只对称的功率开关管每次只有一个导通 所以导通损
  • 数据库数据恢复-Oracle数据库数据恢复案例

    数据库数据恢复环境 Oracle数据库ASM磁盘组有4块成员盘 数据库故障 分析 Oracle数据库ASM磁盘组掉线 ASM实例无法挂载 用户联系我们要求恢复oracle数据库 数据库数据恢复工程师拿到磁盘后 先将所有磁盘以只读方式进行扇区
  • 第六天 01-hydra工具windows远程桌面的密码爆破

    windows远程桌面的密码爆破 概述 RDP是Windows的远程桌面协议 所占用的端口默认为3389 这个是可以修改的 要求 我们要暴力破解3389号端口的前提是对方的3389号端口是开放的 爆破工具 kali使用hydra 九头蛇 工
  • python文件开头两行#!/usr/bin/python和# -*- coding:utf-8 -*-解释以及Pycharm自动创建py文件头部信息

    我们常见到python文件的前两行都会写上如下两行代码 下面我分别解释这两条语句的意义 并介绍pycharm中自动生成py文件头部信息的方法 usr bin env python coding utf 8 或者 usr bin python
  • vs2019 中编译和使用 protobuf 库

    背景 protobuf 是一种跨平台的序列化结构数据的方法 可用于网络数据传输及存储 本文对使用 vs2019 编译 protobuf 库文件进行说明 相关代码及安装文件均来自官网下载 VS2019 编译 protobuf 生成 sln 工
  • 实时语音通讯技术的应用场景与挑战

    随着互联网和移动通信技术的快速发展 实时语音通讯技术已经成为人们日常生活和工作中不可或缺的一部分 实时语音通讯技术可以让人们通过网络进行实时语音通话 不受时间和地点的限制 带来了极大的便利和效率提升 本文将探讨实时语音通讯技术的应用场景和挑
  • Java并发之ThreadLocal源码分析(第二篇:添加元素)

    前言 两个与添加元素相关的方法 initialValue 用于初始化一个默认值 set 用于添加一个元素 set 方法分析 public void set T value Thread t Thread currentThread Thre