当前位置: 首页 > news >正文

Netty中FastThreadLocal解读

io.netty.util.concurrent.FastThreadLocal 是 Netty 中提供的高性能线程局部存储(Thread-Local Storage)实现,位于 io.netty.util.concurrent 包。它是 Java 标准库 ThreadLocal 的替代品,旨在优化性能,减少内存分配和访问开销,特别适合 Netty 的高并发异步框架。FastThreadLocal 依赖 io.netty.util.internal.InternalThreadLocalMap 实现高效存储,广泛用于 EventLoop、对象池(如 Recycler)、和性能敏感场景。


1. 源码分析

FastThreadLocal 使用 InternalThreadLocalMap (请见https://blog.csdn.net/eclipseC/article/details/149756328?spm=1001.2014.3001.5501)的 indexedVariables 数组存储线程局部变量,通过全局唯一的索引(由 InternalThreadLocalMap.nextVariableIndex() 分配)访问。

源码注释

/*** FastThreadLocal 是 Netty 的高性能线程局部存储实现,优于 Java 的 ThreadLocal。* 通过 InternalThreadLocalMap 的索引数组存储变量,减少哈希表开销。* 每个 FastThreadLocal 实例分配一个唯一索引,用于访问线程局部变量。* @param <V> 线程局部变量的类型*/
public class FastThreadLocal<V> {/*** 分配唯一的索引,用于在 InternalThreadLocalMap 中存储变量。*/private final int index = InternalThreadLocalMap.nextVariableIndex();/*** 获取当前线程的线程局部变量值。* @return 变量值,如果未设置则调用 initialize 初始化*/public final V get() {return get(InternalThreadLocalMap.get()); // 获取当前线程的 map}/*** 从指定的 InternalThreadLocalMap 获取变量值。* @param threadLocalMap 当前线程的 InternalThreadLocalMap* @return 变量值,如果未设置则初始化*/@SuppressWarnings("unchecked")public final V get(InternalThreadLocalMap threadLocalMap) {Object v = threadLocalMap.indexedVariable(index); // 获取索引处的值if (v != InternalThreadLocalMap.UNSET) { // 如果不是 UNSET,直接返回return (V) v;}return initialize(threadLocalMap); // 初始化并返回}/*** 设置当前线程的线程局部变量值。* @param value 要设置的值*/public final void set(V value) {if (value != InternalThreadLocalMap.UNSET) { // 避免设置 UNSETset(InternalThreadLocalMap.get(), value);} else {remove(); // 设置 UNSET 等同于移除}}/*** 在指定的 InternalThreadLocalMap 中设置变量值。* @param threadLocalMap 当前线程的 InternalThreadLocalMap* @param value 要设置的值*/public final void set(InternalThreadLocalMap threadLocalMap, V value) {if (value != InternalThreadLocalMap.UNSET) {if (threadLocalMap.setIndexedVariable(index, value)) { // 设置值addToVariablesToRemove(threadLocalMap, this); // 加入清理列表}} else {remove(threadLocalMap); // 移除变量}}/*** 移除当前线程的线程局部变量。*/public final void remove() {remove(InternalThreadLocalMap.get());}/*** 在指定的 InternalThreadLocalMap 中移除变量。* @param threadLocalMap 当前线程的 InternalThreadLocalMap*/@SuppressWarnings("unchecked")public final void remove(InternalThreadLocalMap threadLocalMap) {Object v = threadLocalMap.indexedVariable(index);if (v != InternalThreadLocalMap.UNSET) { // 如果变量存在threadLocalMap.setIndexedVariable(index, InternalThreadLocalMap.UNSET); // 设置为 UNSETremoveFromVariablesToRemove(threadLocalMap, this); // 从清理列表移除try {onRemoval((V) v); // 调用清理回调} catch (Exception e) {PlatformDependent.throwException(e);}}}/*** 初始化线程局部变量值。* @param threadLocalMap 当前线程的 InternalThreadLocalMap* @return 初始值*/protected V initialize(InternalThreadLocalMap threadLocalMap) {V v = null;try {v = initialValue(); // 调用子类的初始值方法} catch (Exception e) {PlatformDependent.throwException(e);}threadLocalMap.setIndexedVariable(index, v); // 设置初始值addToVariablesToRemove(threadLocalMap, this); // 加入清理列表return v;}/*** 提供默认的初始值,子类可重写。* @return 默认返回 null* @throws Exception 如果初始化失败*/protected V initialValue() throws Exception {return null;}/*** 当变量被移除时调用,子类可重写以实现清理逻辑。* @param value 被移除的变量值* @throws Exception 如果清理失败*/protected void onRemoval(@SuppressWarnings("UnusedParameters") V value) throws Exception {}
}

2. 作用与功能

FastThreadLocal 是 Netty 优化的线程局部存储实现,其主要作用包括:

  1. 高性能存储

    • 使用 InternalThreadLocalMapindexedVariables 数组,通过整数索引访问变量,相比 Java ThreadLocalHashMap 实现,减少了哈希计算和冲突处理开销。
    • 每个 FastThreadLocal 实例分配一个唯一索引(index),通过 InternalThreadLocalMap.nextVariableIndex() 生成。
  2. 线程隔离

    • 确保每个线程的变量独立存储,适合 Netty 的单线程 EventLoop 模型。
    • 配合 FastThreadLocalThread 进一步优化性能,减少 ThreadLocal 的访问开销。
  3. 支持清理机制

    • 提供 remove 方法和 onRemoval 回调,允许清理线程局部变量,防止内存泄漏。
    • 维护 variablesToRemove 列表,跟踪需要清理的 FastThreadLocal 实例。
  4. 支持 Netty 功能模块

    • 对象池(Recycler):存储对象池的上下文数据,优化 ByteBuf 等对象的复用。
    • 上下文管理:在 EventLoopChannelPipeline 中存储线程特定的状态。
    • 性能优化:减少反射和内存分配,适用于高并发场景。

3. 关键方法解析

以下是 FastThreadLocal 的核心方法及其作用:

3.1 get
  • 签名public final V get()
  • 作用:获取当前线程的线程局部变量值。
  • 逻辑
    • 调用 InternalThreadLocalMap.get() 获取当前线程的 InternalThreadLocalMap
    • 通过 indexindexedVariables 获取值。
    • 如果值为 UNSET,调用 initialize 初始化。
  • 使用场景:获取线程局部变量,如对象池中的 ByteBuf
3.2 set
  • 签名public final void set(V value)
  • 作用:设置当前线程的线程局部变量值。
  • 逻辑
    • 如果 value != UNSET,设置值并加入清理列表。
    • 如果 value == UNSET,调用 remove 移除变量。
  • 使用场景:设置线程特定的上下文,如 Recycler 的对象池。
3.3 remove
  • 签名public final void remove()
  • 作用:移除当前线程的线程局部变量。
  • 逻辑
    • 检查变量是否为 UNSET,若不是,设置为 UNSET,从清理列表移除,并调用 onRemoval
  • 使用场景:清理不再需要的变量,防止内存泄漏。
3.4 initialize
  • 签名protected V initialize(InternalThreadLocalMap threadLocalMap)
  • 作用:初始化线程局部变量值。
  • 逻辑
    • 调用 initialValue() 获取默认值(子类可重写)。
    • 设置值到 indexedVariables 并加入清理列表。
  • 使用场景:首次访问变量时提供初始值。
3.5 initialValue
  • 签名protected V initialValue() throws Exception
  • 作用:提供默认初始值,子类可重写。
  • 默认实现:返回 null
  • 使用场景:自定义初始值,如初始化对象池的默认对象。
3.6 onRemoval
  • 签名protected void onRemoval(V value) throws Exception
  • 作用:变量移除时的回调,子类可重写以实现清理逻辑。
  • 使用场景:释放资源,如对象池中的对象回收。

4. 与 InternalThreadLocalMap 的关系

FastThreadLocal 依赖 InternalThreadLocalMap 实现存储:

  • 索引分配:每个 FastThreadLocal 实例通过 InternalThreadLocalMap.nextVariableIndex() 分配唯一索引,存储在 indexedVariables 数组中。
  • 高效访问
    • getset 方法通过索引直接访问 indexedVariables,避免 ThreadLocal 的哈希表操作。
    • InternalThreadLocalMap.UNSET 标记未设置的槽位,区分 null 值。
  • 清理机制InternalThreadLocalMap 维护 variablesToRemove 列表,FastThreadLocalsetremove 方法更新该列表,确保变量可被清理。

5. 使用场景

FastThreadLocal 的主要应用场景包括:

  1. 对象池(Recycler)

    • 存储线程局部的对象池上下文,优化 ByteBuf 等对象的复用。
    • 示例:
      private static final FastThreadLocal<Recycler.Handle> HANDLE = new FastThreadLocal<Recycler.Handle>() {@Overrideprotected Recycler.Handle initialValue() {return new Recycler.Handle();}
      };
      
  2. 上下文管理

    • EventLoopChannelPipeline 中存储线程特定的状态。
    • 示例:缓存 ChannelHandler 的处理状态。
  3. 随机数生成

    • 配合 InternalThreadLocalMaprandom 字段,提供线程局部的随机数生成器。
    • 示例:负载均衡选择 EventLoop
  4. 性能敏感场景

    • 在高并发场景中,FastThreadLocal 提供低开销的线程局部变量访问。
    • 示例:NioEventLoop 中存储临时 I/O 上下文。

6. 与 Java ThreadLocal 的对比

特性FastThreadLocalThreadLocal
存储方式基于 InternalThreadLocalMap 的数组索引基于 ThreadLocalMap 的哈希表
性能高,索引访问避免哈希计算较低,哈希表操作可能有冲突
线程支持优化 FastThreadLocalThread,兼容普通线程支持所有线程
清理机制提供 removeonRemoval 回调,防止泄漏需手动调用 remove,易泄漏
使用场景Netty 内部,如对象池、事件循环上下文通用线程局部存储
http://www.dtcms.com/a/305286.html

相关文章:

  • C++多态:面向对象编程的灵魂之
  • Linux_库制作与原理浅理解
  • 青木川古镇
  • Flex布局面试常考的场景题目
  • 墨者:SQL过滤字符后手工注入漏洞测试(第3题)
  • MC0244多重堡垒
  • kotlin使用mybatis plus lambdaQuery报错
  • Java中什么是类加载?类加载的过程?
  • TGD第八篇:二维应用——图像边缘检测
  • FastAPI入门:Cookie参数、Header参数、Cookie参数模型、Header参数模型
  • 移动端 WebView 调试实战,多平台行为差异排查与统一调试流程
  • Gartner发布CTEM指南:使用持续威胁暴露管理来减少网络攻击
  • 应急前端“黄金3分钟”设计:极端场景下的操作界面极速搭建技术
  • COPRAS(Complex Proportional Assessment)简介与简单示例
  • 汇总10个高质量免费AI生成论文网站,支持GPT4.0和DeepSeek-R1
  • [学习记录]URP流程解析(2)--初始化阶段
  • 最新优茗导航系统源码/全开源版本/精美UI/带后台/附教程
  • Effective_C++09: 绝不在构造和析构过程中调用virtual函数
  • 【解决办法】pip install albumentations安装下载遇19kB/s超级慢细水管
  • 无代码测试平台ATECLOUD全场景测试方案
  • Java中Boolean.getBoolean方法误用与修复
  • 【监控】非IP监控系统改造IP监控系统
  • 中科米堆CASAIM空调扇叶自动蓝光三维测量解决方案
  • <RT1176系列12>DMAMUX入门级应用和DMAMUX MAP表
  • Linux定时器和时间管理源码相关总结
  • 【Unity编辑器扩展】Unity场景选择工具 - ScenesChooseTool 使用指南
  • 项目历程—生命数组游戏(两版本)
  • 智源研究院发布数据魔方,以智能化自定义方式重构模型训练数据供给范式
  • 两数之和(每天刷力扣hot100系列)
  • JDK17 新特性跟学梳理