FastThreadLocal 原理解析
FastThreadLocal

- 每个 FastThread 包含一个 FastThreadLocalMap,每个 FastThreadLocalThread 中的多个 FastThreadLocal 占用不同的索引。
- 每个 InternalThreadLocalMap 的第一个元素保存了所有的 ThreadLocal 对象。之后的元素保存了每个 ThreadLocal 对应的 value
基本操作
get()
当前线程中
- 找到 ThreadLocal 的 index,value 加入 InternalThreadLocalMap 对应索引的位置
set()
当前线程中
- 找到 ThreadLocal 的 index,value 加入 InternalThreadLocalMap 对应索引的位置
- 将 ThreadLocal 加入当前线程 InternalThreadLocalMap 的第一个元素对应的集合
remove()
当前线程中
- 找到 ThreadLocal 的 index,InternalThreadLocalMap 中 index 对应的 value 置为 UNSET
- 将 ThreadLocal 从当前线程 InternalThreadLocalMap 的第一个元素集合中删除
关键设计点
兼容 ThreadLocal
当线程没有使用 FastThreadLocal 的时候,默认走 ThreadLocal 的逻辑。
初始大小
初始大小为 32
hash 算法
直接使用全局的自增,不存在Hash 冲突,以空间换时间
扩容条件是什么?如何扩容?
- 扩容条件:当前线程元素超出容量
- 扩容:元素数量扩展为向上取最近 2 次幂整数,比如,5 取8,31 取 64。
public boolean setIndexedVariable(int index, Object value) {Object[] lookup = indexedVariables;// index 大于容量if (index < lookup.length) {Object oldValue = lookup[index];lookup[index] = value;return oldValue == UNSET;} else {// 扩容expandIndexedVariableTableAndSet(index, value);return true;}}private void expandIndexedVariableTableAndSet(int index, Object value) {Object[] oldArray = indexedVariables;final int oldCapacity = oldArray.length;int newCapacity;// 当小于 2的30次方时,容量扩展为向上取最近 2 次幂整数,比如,5 取8,31 取 64。if (index < ARRAY_LIST_CAPACITY_EXPAND_THRESHOLD) {newCapacity = index;newCapacity |= newCapacity >>> 1;newCapacity |= newCapacity >>> 2;newCapacity |= newCapacity >>> 4;newCapacity |= newCapacity >>> 8;newCapacity |= newCapacity >>> 16;newCapacity ++;} else {newCapacity = ARRAY_LIST_CAPACITY_MAX_SIZE;}Object[] newArray = Arrays.copyOf(oldArray, newCapacity);Arrays.fill(newArray, oldCapacity, newArray.length, UNSET);newArray[index] = value;indexedVariables = newArray;}
如何防止内存泄漏
自动: 使用ftlt执行一个被FastThreadLocalRunnable wrap的Runnable任务,在任务执行完毕后会自动进行ftl的清理。
final class FastThreadLocalRunnable implements Runnable {private final Runnable runnable;private FastThreadLocalRunnable(Runnable runnable) {this.runnable = ObjectUtil.checkNotNull(runnable, "runnable");}@Overridepublic void run() {try {runnable.run();} finally {FastThreadLocal.removeAll();}}static Runnable wrap(Runnable runnable) {return runnable instanceof FastThreadLocalRunnable ? runnable : new FastThreadLocalRunnable(runnable);}
}
手动: ftl和InternalThreadLocalMap都提供了remove方法,在合适的时候用户可以(有的时候也是必须,例如普通线程的线程池使用ftl)手动进行调用,进行显示删除。
使用
final class FastThreadLocalRunnable implements Runnable {private final Runnable runnable;private FastThreadLocalRunnable(Runnable runnable) {this.runnable = (Runnable)ObjectUtil.checkNotNull(runnable, "runnable");}public void run() {try {this.runnable.run();} finally {// 如果用的是 FastThreadLocalRunnable ,默认会做清理FastThreadLocal.removeAll();}}static Runnable wrap(Runnable runnable) {return (Runnable)(runnable instanceof FastThreadLocalRunnable ? runnable : new FastThreadLocalRunnable(runnable));}
}
存在什么问题
1、空间浪费,所有线程的 ThreadLocalMap 数组大小是一样的
比如,线程1 创建 100 个 ThreadLocal 对象。线程 1 里面有一个长度为 100 的数组。
此时,第二个线程需要调用 ThreadLocal 100 的 get 方法,第二个线程需要分配 100 个 Object 对象。
import io.netty.util.concurrent.FastThreadLocal;
import io.netty.util.concurrent.FastThreadLocalThread;import java.util.ArrayList;
import java.util.List;public class FastThreadLocalTest {private List<FastThreadLocal<String>> fastThreadLocals = new ArrayList<>();private List<ThreadLocal<String>> threadLocals = new ArrayList<>();void thread1Init() {new Thread (() -> {for (int i = 0; i < 31; i++) {ThreadLocal<String> threadLocal = new ThreadLocal<>();threadLocal.get();threadLocals.add(threadLocal);}}).start();}void thread2Init() {new Thread(() -> {threadLocals.get(threadLocals.size() - 1).get();});}void fastThread1Init() {new FastThreadLocalThread (() -> {for (int i = 0; i < 33; i++) {FastThreadLocal<String> fastThreadLocal = new FastThreadLocal<>();fastThreadLocal.get();fastThreadLocals.add(fastThreadLocal);}}).start();}void fastThread2Init() {new FastThreadLocalThread(() -> {fastThreadLocals.get(fastThreadLocals.size() - 1).get();});}public static void main(String[] args) {FastThreadLocalTest test = new FastThreadLocalTest();test.fastThread1Init();test.fastThread2Init();test.thread1Init();test.thread2Init();}
}
2、FastThreadLocal 需要配套 FastThreadLocalThread 使用,不然还不如原生 ThreadLocal。
3、FastThreadLocal 使用最好配套 FastThreadLocalRunnable,这样执行完任务后会主动调用 removeAll 来移除所有
性能压测
netty 官方 mincrobench
相关文章:
FastThreadLocal 原理解析
FastThreadLocal 每个 FastThread 包含一个 FastThreadLocalMap,每个 FastThreadLocalThread 中的多个 FastThreadLocal 占用不同的索引。每个 InternalThreadLocalMap 的第一个元素保存了所有的 ThreadLocal 对象。之后的元素保存了每个 ThreadLocal 对应的 value …...
设计模式B站学习(一)(java)
这里写目录标题 一、设计模式概述1.1 软件设计模式的产生背景1.2 软件设计模式的概念1.3 学习设计模式的必要性1.4 设计模式分类 二、UML图2.1 类图概述2.2 类图的作用2.3 类图表示法2.3.1 类图表示方法2.3.2 类与类之间关系的表示方法2.3.2.1 关联关系2.3.2.2 聚合关系2.3.2.3…...
Pandas如何轻松按位置删除多重索引列?
在Pandas处理DataFrame数据的过程中,我们常常需要删除某些不需要的列。那么,如何高效地按位置删除Pandas DataFrame的多重索引列呢? 今天分享在Pandas中按位置删除多重索引列的具体方法: 第一步:获取所有列标签 使用df.columns获取DataFrame的所有列标…...
第五十七天学习记录:C语言进阶:结构体链表的自学
先展示一段代码: #define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h> #include <stdlib.h>// 定义链表节点结构体 typedef struct Node {int value;struct Node* next; } Node;int main() {// 创建链表头指针Node* head (Node*)malloc(sizeof(Node…...
【一次调频】考虑储能电池参与一次调频技术经济模型的容量配置方法(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
ICV报告: 智能座舱SoC全球市场规模预计2025年突破50亿美元
在智能化、互联化车辆需求不断增加的推动下,汽车行业正在经历一场范式转变。这一转变的前沿之一是智能座舱SoC。本市场研究报告对智能座舱SoC市场进行了全面的分析,包括其应用领域、当前状况和主要行业参与者。 智能座舱SoC指的是现代汽车智能座舱系统的…...
在can协议的基础下编写DBC文件,然后使用该DBC文件下发can协议到底盘完整流程
目录 前言一、VectorCANdb下载及安装二、DBC文件的编写1.新建dbc文件2.建立dbc2.1根据CAN协议设置以下的signals2.2设置报文2.3建立报文与信号的关系2.4建立节点 三、编写程序使用UDP通信下发can协议1.查看can口、电脑ip以及端口号2.编写测试程序 前言 最近完成了一个项目&…...
工业传感器有哪些?
工业传感器是指能在工业制造过程能将感受的力、热、光、磁、声、湿、电、环境等被测量转换成电信号输出的器件与装置,在各种化工、机械、汽车等工业场景上都有应用。 工业传感器有哪些? 工业传感器由于不同的特性也被分为多种不同的类别,主要…...
Docker应用部署之Nginx
部署nginx 要求:在docker容器中部署nginx,并通过外部机器访问nginx 步骤: 1.搜索nginx镜像 docker search nginx 2.拉取nginx镜像 docker pull nginx 3.创建容器 #在root目录下创建nginx目录用于存放nginx项目 mkdir ~/nginx cd ~/ng…...
TerminalWorks TSPrint/TSScan/TSWebCam Crack
/ 远程桌面打印软件,TerminalWorks TSPrint Server/Client 从远程服务器打印到本地打印机的 简单方法 TSPrint 为您提供了一个简单的远程桌面打印软件,以及使 Windows 终端服务操作更容易的附加工具。有选择地启用或禁用功能,以便您可以完全…...
如何使用Springboot实现文件上传和下载,并为其添加实时进度条的功能
文件上传和下载是Web开发中非常基础的功能,但在实际开发中,我们经常需要实时显示文件上传或下载的进度。这篇文章将介绍如何使用Springboot实现文件上传和下载,并为其添加实时进度条的功能。 文件上传 添加Maven依赖项 首先,我…...
安装并新建windows下wxwroks7.0 bootrom工程
双击steup.exe 直接next 直接next 选择typical,然后next I accept 安装完成finish 现在双击Workbench 4,新建vxworks7.0工程,会出现下面的情况,因为没有licence 安装licence,将zwrsLicense-vx7-perm.lic粘贴到安装目…...
element-ui表格el-table的使用
先给大家展示一下效果 Table 属性 属性名说明类型可选值默认值data显示的数据array——heightTable 的高度, 默认为自动高度。 如果 height 为 number 类型,单位 px;如果 height 为 string 类型,则这个高度会设置为 Table 的 sty…...
Backtrader官方中文文档:第八章Indicators指标
本文档参考backtrader官方文档,是官方文档的完整中文翻译,可作为backtrader中文教程、backtrader中文参考手册、backtrader中文开发手册、backtrader入门资料使用。 Indicators指标章节目录 指标(Indicator)指标的使用__init__ 对比 next指标在`__init__`阶段的执行过程指标在…...
CAP原则
CAP原则又称CAP定理,指的是在一个分布式系统中,存在Consistency(一致性)、Availability(可用性)、Partition tolerance(分区容错性),三者不可同时保证,最多只…...
【PowerQuery】M语言的使用产品和使用场景
当然PowerQuery的M语言应用场景不只是引用在PowerBI和Excel中,它具有广泛的应用场景。目前我们可以在以下产品的使用场景中应用到M语言。 Excel PowerQuery应用Excel通过M语言可以实现整体数据的清洗和重构。 PowerBI 的PowerQuery应用 PowerBI也是通过M语言来实现数据…...
【Linux】遇事不决,可先点灯,LED驱动的进化之路---1
【Linux】遇事不决,可先点灯,LED驱动的进化之路---1 前言: 一、最简单的LED驱动程序 1.1 字符设备驱动程序框架 1.2 程序实战 1.2.1 驱动程序(led_drive_simple.c) 1.2.2 应用程序(led_test_simple.c…...
hive任务reduce步骤卡在99%原因及解决
我们在写sql的时候经常发现读取数据不多,但是代码运行时间异常长的情况,这通常是发生了数据倾斜现象。数据倾斜现象本质上是因为数据中的key分布不均匀,大量的数据集中到了一台或者几台机器上计算,这些数据的计算速度远远低于平均…...
C++11 -- lambda表达式
文章目录 lamaba表达式的引入lambda表达式语法lamabda达式各部分说明捕获列表说明 lamaba表达式底层原理探索 lamaba表达式的引入 在C11之前,如果我们想对自定义类型Goods排序,可以根据姓名,价格,学号按照从大到小或者从小到大的方式排序,可是,这样我们要写额外写6个相关的仿函…...
【开源项目】银行查询服务的设计和实现
银行查询服务的设计和实现 项目地址github:https://github.com/xl-echo/bankInquiryService项目地址gitee:https://gitee.com/xl-echo/bank-inquiry-service 银行查询服务的设计初衷是:为提供更加便利的查询服务,我们在分布式系…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
css的定位(position)详解:相对定位 绝对定位 固定定位
在 CSS 中,元素的定位通过 position 属性控制,共有 5 种定位模式:static(静态定位)、relative(相对定位)、absolute(绝对定位)、fixed(固定定位)和…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
Web中间件--tomcat学习
Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...
