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.youkuaiyun.com/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) { // 避免设置 UNSET
set(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); // 设置为 UNSET
removeFromVariablesToRemove(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 优化的线程局部存储实现,其主要作用包括:
-
高性能存储:
- 使用
InternalThreadLocalMap的indexedVariables数组,通过整数索引访问变量,相比 JavaThreadLocal的HashMap实现,减少了哈希计算和冲突处理开销。 - 每个
FastThreadLocal实例分配一个唯一索引(index),通过InternalThreadLocalMap.nextVariableIndex()生成。
- 使用
-
线程隔离:
- 确保每个线程的变量独立存储,适合 Netty 的单线程
EventLoop模型。 - 配合
FastThreadLocalThread进一步优化性能,减少ThreadLocal的访问开销。
- 确保每个线程的变量独立存储,适合 Netty 的单线程
-
支持清理机制:
- 提供
remove方法和onRemoval回调,允许清理线程局部变量,防止内存泄漏。 - 维护
variablesToRemove列表,跟踪需要清理的FastThreadLocal实例。
- 提供
-
支持 Netty 功能模块:
- 对象池(Recycler):存储对象池的上下文数据,优化
ByteBuf等对象的复用。 - 上下文管理:在
EventLoop或ChannelPipeline中存储线程特定的状态。 - 性能优化:减少反射和内存分配,适用于高并发场景。
- 对象池(Recycler):存储对象池的上下文数据,优化
3. 关键方法解析
以下是 FastThreadLocal 的核心方法及其作用:
3.1 get
- 签名:
public final V get() - 作用:获取当前线程的线程局部变量值。
- 逻辑:
- 调用
InternalThreadLocalMap.get()获取当前线程的InternalThreadLocalMap。 - 通过
index从indexedVariables获取值。 - 如果值为
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数组中。 - 高效访问:
get和set方法通过索引直接访问indexedVariables,避免ThreadLocal的哈希表操作。InternalThreadLocalMap.UNSET标记未设置的槽位,区分null值。
- 清理机制:
InternalThreadLocalMap维护variablesToRemove列表,FastThreadLocal的set和remove方法更新该列表,确保变量可被清理。
5. 使用场景
FastThreadLocal 的主要应用场景包括:
-
对象池(Recycler):
- 存储线程局部的对象池上下文,优化
ByteBuf等对象的复用。 - 示例:
private static final FastThreadLocal<Recycler.Handle> HANDLE = new FastThreadLocal<Recycler.Handle>() { @Override protected Recycler.Handle initialValue() { return new Recycler.Handle(); } };
- 存储线程局部的对象池上下文,优化
-
上下文管理:
- 在
EventLoop或ChannelPipeline中存储线程特定的状态。 - 示例:缓存
ChannelHandler的处理状态。
- 在
-
随机数生成:
- 配合
InternalThreadLocalMap的random字段,提供线程局部的随机数生成器。 - 示例:负载均衡选择
EventLoop。
- 配合
-
性能敏感场景:
- 在高并发场景中,
FastThreadLocal提供低开销的线程局部变量访问。 - 示例:
NioEventLoop中存储临时 I/O 上下文。
- 在高并发场景中,
6. 与 Java ThreadLocal 的对比
| 特性 | FastThreadLocal | ThreadLocal |
|---|---|---|
| 存储方式 | 基于 InternalThreadLocalMap 的数组索引 | 基于 ThreadLocalMap 的哈希表 |
| 性能 | 高,索引访问避免哈希计算 | 较低,哈希表操作可能有冲突 |
| 线程支持 | 优化 FastThreadLocalThread,兼容普通线程 | 支持所有线程 |
| 清理机制 | 提供 remove 和 onRemoval 回调,防止泄漏 | 需手动调用 remove,易泄漏 |
| 使用场景 | Netty 内部,如对象池、事件循环上下文 | 通用线程局部存储 |
1201

被折叠的 条评论
为什么被折叠?



