Netty源码分析----FastThreadLocal深度解析

基于大语言模型的学术论文阅读辅助分析系统的研究与应用 本文提出了一种基于大语言模型的学术论文阅读辅助分析系统PaperMind,旨在解决传统学术阅读方式面临的三大困境:信息定位困难、跨学科知识断层和手动整理耗时。系统采用检索增强生成(RAG)架构,通过PDF文档解析、语义分割、向量嵌入与FAISS向量检索相结合的技术路线,构建了完整的文档处理流水线。实验结果表明,系统在文档加载分割、向量检索与问答生成环节均达到预期性能指标,检索命中率最高达98%。该系统为学术文献智能化处理提供了可复用的技术方案,有效解决了通用大语言模型在学术场景中的幻觉引用、归因能力不足等问 阅读详情

FastThreadLocal 深度解析

一、JDK ThreadLocal 的实现与问题

1.1 ThreadLocal 的基本使用

public class ThreadLocalExample {
    // 创建 ThreadLocal 变量
    private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
    
    public static void main(String[] args) {
        // 线程 1
        new Thread(() -> {
            threadLocal.set("Thread-1 的值");
            System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());
        }, "Thread-1").start();
        
        // 线程 2
        new Thread(() -> {
            threadLocal.set("Thread-2 的值");
            System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());
        }, "Thread-2").start();
    }
}

// 输出:
// Thread-1: Thread-1 的值
// Thread-2: Thread-2 的值

ThreadLocal 的作用:

  • 为每个线程提供独立的变量副本
  • 避免线程间的数据竞争
  • 常用于存储线程上下文信息(如用户信息、事务信息等)

1.2 JDK ThreadLocal 的实现原理

核心数据结构:

// Thread.java
public class Thread {
    // 每个线程都有一个 ThreadLocalMap
    ThreadLocal.ThreadLocalMap threadLocals = null;
}

// ThreadLocal.java
public class ThreadLocal<T> {
    
    // 获取值
    public T get() {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);  // 获取当前线程的 Map
        if (map != null) {
            ThreadLocalMap.Entry e = map.getEntry(this);  // 以 ThreadLocal 为 key
            if (e != null) {
                return (T)e.value;
            }
        }
        return setInitialValue();
    }
    
    // 设置值
    public void set(T value) {
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);  // 以 ThreadLocal 为 key
        else
            createMap(t, value);
    }
    
    ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
    }
}

ThreadLocalMap 的实现:

// ThreadLocal.ThreadLocalMap
static class ThreadLocalMap {
    
    // Entry 继承 WeakReference,key 是弱引用
    static class Entry extends WeakReference<ThreadLocal<?>> {
        Object value;
        
        Entry(ThreadLocal<?> k, Object v) {
            super(k);
            value = v;
        }
    }
    
    // 底层是数组
    private Entry[] table;
    
    // 初始容量
    private static final int INITIAL_CAPACITY = 16;
    
    // 负载因子
    private int threshold;
    
    // 构造函数
    ThreadLocalMap(ThreadLocal<?> firstKey, Object firstValue) {
        table = new Entry[INITIAL_CAPACITY];
        int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);
        table[i] = new Entry(firstKey, firstValue);
        size = 1;
        setThreshold(INITIAL_CAPACITY);
    }
    
    // 获取值
    private Entry getEntry(ThreadLocal<?> key) {
        int i = key.threadLocalHashCode & (table.length - 1);
        Entry e = table[i];
        if (e != null && e.get() == key)
            return e;
        else
            return getEntryAfterMiss(key, i, e);  // 处理哈希冲突
    }
    
    // 设置值
    private void set(ThreadLocal<?> key, Object value) {
        Entry[] tab = table;
        int len = tab.length;
        int i = key.threadLocalHashCode & (len-1);  // 计算哈希值

        // 线性探测法解决哈希冲突
        for (Entry e = tab[i];
             e != null;
             e = tab[i = nextIndex(i, len)]) {
            ThreadLocal<?> k = e.get();

            if (k == key) {
                e.value = value;
                return;
            }

            if (k == null) {
                replaceStaleEntry(key, value, i);
                return;
            }
        }

        tab[i] = new Entry(key, value);
        int sz = ++size;
        if (!cleanSomeSlots(i, sz) && sz >= threshold)
            rehash();
    }
    
    // 线性探测:下一个索引
    private static int nextIndex(int i, int len) {
        return ((i + 1 < len) ? i + 1 : 0);
    }
}

1.3 JDK ThreadLocal 的性能问题

问题 1:哈希冲突

ThreadLocalMap 使用线性探测法解决哈希冲突:

初始状态:
[null, null, null, null, null, null, null, null]

插入 ThreadLocal1 (hash=2):
[null, null, TL1, null, null, null, null, null]

插入 ThreadLocal2 (hash=2,冲突):
[null, null, TL1, TL2, null, null, null, null]
                    ↑ 线性探测,放到下一个位置

插入 ThreadLocal3 (hash=2,冲突):
[null, null, TL1, TL2, TL3, null, null, null]
                         ↑ 继续线性探测

查找 ThreadLocal3:
1. 计算 hash = 2
2. table[2] = TL1,不匹配
3. table[3] = TL2,不匹配
4. table[4] = TL3,匹配!

性能问题:
- 需要多次比较
- 时间复杂度 O(n),最坏情况遍历整个数组

问题 2:哈希计算

// ThreadLocal.java
private final int threadLocalHashCode = nextHashCode();

private static AtomicInteger nextHashCode = new AtomicInteger();

private static final int HASH_INCREMENT = 0x61c88647;

private static int nextHashCode() {
    return nextHashCode.getAndAdd(HASH_INCREMENT);
}

// 每次创建 ThreadLocal 都要计算哈希值
// 使用魔数 0x61c88647 保证分布均匀

问题 3:扩容开销

// ThreadLocalMap.java
private void resize() {
    Entry[] oldTab = table;
    int oldLen = oldTab.length;
    int newLen = oldLen * 2;  // 扩容为 2 倍
    Entry[] newTab = new Entry[newLen];
    int count = 0;

    // 重新哈希所有元素
    for (int j = 0; j < oldLen; ++j) {
        Entry e = oldTab[j];
        if (e != null) {
            ThreadLocal<?> k = e.get();
            if (k == null) {
                e.value = null;
            } else {
                int h = k.threadLocalHashCode & (newLen - 1);
                while (newTab[h] != null)
                    h = nextIndex(h, newLen);
                newTab[h] = e;
                count++;
            }
        }
    }

    setThreshold(newLen);
    size = count;
    table = newTab;
}

性能测试:

public class ThreadLocalBenchmark {
    public static void main(String[] args) {
        int iterations = 1_000_000;
        
        // 创建 10 个 ThreadLocal
        ThreadLocal<String>[] threadLocals = new ThreadLocal[10];
        for (int i = 0; i < 10; i++) {
            threadLocals[i] = new ThreadLocal<>();
        }
        
        long start = System.nanoTime();
        
        for (int i = 0; i < iterations; i++) {
            // 设置值
            for (ThreadLocal<String> tl : threadLocals) {
                tl.set("value-" + i);
            }
            
            // 获取值
            for (ThreadLocal<String> tl : threadLocals) {
                tl.get();
            }
        }
        
        long end = System.nanoTime();
        System.out.println("JDK ThreadLocal 耗时: " + (end - start) / 1_000_000 + " ms");
    }
}

// 输出:
// JDK ThreadLocal 耗时: 450 ms

二、FastThreadLocal 的优化思路

2.1 核心优化:数组代替哈希表

JDK ThreadLocal:

ThreadLocal1 → hash → index → 线性探测 → 找到位置
ThreadLocal2 → hash → index → 线性探测 → 找到位置
ThreadLocal3 → hash → index → 线性探测 → 找到位置

时间复杂度:O(n)(最坏情况)

FastThreadLocal:

FastThreadLocal1 → index = 0 → 直接访问 array[0]
FastThreadLocal2 → index = 1 → 直接访问 array[1]
FastThreadLocal3 → index = 2 → 直接访问 array[2]

时间复杂度:O(1)(常数时间)

2.2 设计思想

关键点:

  1. 每个 FastThreadLocal 有一个全局唯一的索引(index)
  2. 使用数组存储值,通过索引直接访问
  3. 避免哈希计算和冲突解决

对比:

特性JDK ThreadLocalFastThreadLocal
数据结构哈希表(数组 + 链表)纯数组
查找方式哈希 + 线性探测直接索引访问
时间复杂度O(n)O(1)
哈希计算需要不需要
冲突解决线性探测无冲突
扩容需要重新哈希简单的数组扩容

三、FastThreadLocal 的实现原理

3.1 核心组件

1. FastThreadLocal

// io.netty.util.concurrent.FastThreadLocal
public class FastThreadLocal<V> {
    
    // 全局索引生成器
    private static final AtomicInteger nextIndex = new AtomicInteger();
    
    // 每个 FastThreadLocal 的唯一索引
    private final int index;
    
    public FastThreadLocal() {
        // 创建时分配一个全局唯一的索引
        index = InternalThreadLocalMap.nextVariableIndex();
    }
    
    // 获取值
    public final V get() {
        InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
        Object v = threadLocalMap.indexedVariable(index);  // 直接通过索引访问
        if (v != InternalThreadLocalMap.UNSET) {
            return (V) v;
        }
        return initialize(threadLocalMap);
    }
    
    // 设置值
    public final void set(V value) {
        if (value != InternalThreadLocalMap.UNSET) {
            InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.get();
            setKnownNotUnset(threadLocalMap, value);
        } else {
            remove();
        }
    }
    
    private void setKnownNotUnset(InternalThreadLocalMap threadLocalMap, V value) {
        // 直接通过索引设置值
        if (threadLocalMap.setIndexedVariable(index, value)) {
            addToVariablesToRemove(threadLocalMap, this);
        }
    }
}

2. InternalThreadLocalMap

// io.netty.util.internal.InternalThreadLocalMap
public final class InternalThreadLocalMap extends UnpaddedInternalThreadLocalMap {
    
    // 未设置的标记
    public static final Object UNSET = new Object();
    
    // 存储值的数组
    private Object[] indexedVariables;
    
    // 初始容量
    private static final int DEFAULT_ARRAY_LIST_INITIAL_CAPACITY = 8;
    
    private InternalThreadLocalMap() {
        super(newIndexedVariableTable());
    }
    
    private static Object[] newIndexedVariableTable() {
        Object[] array = new Object[32];
        Arrays.fill(array, UNSET);
        return array;
    }
    
    // 获取当前线程的 InternalThreadLocalMap
    public static InternalThreadLocalMap get() {
        Thread thread = Thread.currentThread();
        if (thread instanceof FastThreadLocalThread) {
            // 如果是 FastThreadLocalThread,直接获取
            return fastGet((FastThreadLocalThread) thread);
        } else {
            // 否则使用 JDK ThreadLocal 作为降级方案
            return slowGet();
        }
    }
    
    private static InternalThreadLocalMap fastGet(FastThreadLocalThread thread) {
        InternalThreadLocalMap threadLocalMap = thread.threadLocalMap();
        if (threadLocalMap == null) {
            thread.setThreadLocalMap(threadLocalMap = new InternalThreadLocalMap());
        }
        return threadLocalMap;
    }
    
    // 通过索引获取值(O(1))
    public Object indexedVariable(int index) {
        Object[] lookup = indexedVariables;
        return index < lookup.length ? lookup[index] : UNSET;
    }
    
    // 通过索引设置值(O(1))
    public boolean setIndexedVariable(int index, Object value) {
        Object[] lookup = indexedVariables;
        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 = index;
        newCapacity |= newCapacity >>>  1;
        newCapacity |= newCapacity >>>  2;
        newCapacity |= newCapacity >>>  4;
        newCapacity |= newCapacity >>>  8;
        newCapacity |= newCapacity >>> 16;
        newCapacity ++;

        Object[] newArray = Arrays.copyOf(oldArray, newCapacity);
        Arrays.fill(newArray, oldCapacity, newArray.length, UNSET);
        newArray[index] = value;
        indexedVariables = newArray;
    }
    
    // 生成下一个索引
    public static int nextVariableIndex() {
        int index = nextIndex.getAndIncrement();
        if (index < 0) {
            nextIndex.decrementAndGet();
            throw new IllegalStateException("too many thread-local indexed variables");
        }
        return index;
    }
}

3. FastThreadLocalThread

// io.netty.util.concurrent.FastThreadLocalThread
public class FastThreadLocalThread extends Thread {
    
    // 每个线程持有一个 InternalThreadLocalMap
    private InternalThreadLocalMap threadLocalMap;
    
    public FastThreadLocalThread() {
        super();
    }
    
    public FastThreadLocalThread(Runnable target) {
        super(target);
    }
    
    public FastThreadLocalThread(Runnable target, String name) {
        super(target, name);
    }
    
    // 获取 InternalThreadLocalMap
    public final InternalThreadLocalMap threadLocalMap() {
        return threadLocalMap;
    }
    
    // 设置 InternalThreadLocalMap
    public final void setThreadLocalMap(InternalThreadLocalMap threadLocalMap) {
        this.threadLocalMap = threadLocalMap;
    }
}

3.2 工作流程

创建 FastThreadLocal:

1. 创建 FastThreadLocal 实例
   ↓
2. 调用 InternalThreadLocalMap.nextVariableIndex()
   ↓
3. 分配全局唯一的索引(例如:index = 5)
   ↓
4. 保存索引到 FastThreadLocal.index 字段

全局索引分配:
FastThreadLocal1 → index = 0
FastThreadLocal2 → index = 1
FastThreadLocal3 → index = 2
...

设置值:

1. 调用 fastThreadLocal.set(value)
   ↓
2. 获取当前线程的 InternalThreadLocalMap
   ↓
3. 通过索引直接设置值
   threadLocalMap.indexedVariables[index] = value
   
示例:
Thread-1:
  indexedVariables = [value0, value1, value2, UNSET, UNSET, ...]
                       ↑       ↑       ↑
                     index=0  index=1  index=2

Thread-2:
  indexedVariables = [valueA, valueB, valueC, UNSET, UNSET, ...]
                       ↑       ↑       ↑
                     index=0  index=1  index=2

获取值:

1. 调用 fastThreadLocal.get()
   ↓
2. 获取当前线程的 InternalThreadLocalMap
   ↓
3. 通过索引直接获取值
   value = threadLocalMap.indexedVariables[index]
   
时间复杂度:O(1)

3.3 与 JDK ThreadLocal 的对比

JDK ThreadLocal 的查找过程:

// 1. 计算哈希值
int hash = threadLocal.threadLocalHashCode;

// 2. 计算索引
int index = hash & (table.length - 1);

// 3. 线性探测
Entry e = table[index];
while (e != null && e.get() != threadLocal) {
    index = (index + 1) & (table.length - 1);
    e = table[index];
}

// 4. 返回值
return e != null ? e.value : null;

// 时间复杂度:O(n)

FastThreadLocal 的查找过程:

// 1. 直接通过索引访问
Object value = indexedVariables[index];

// 2. 返回值
return value != UNSET ? value : null;

// 时间复杂度:O(1)

性能对比图:

查找时间(纳秒)
  ↑
  |                                    JDK ThreadLocal
  |                                   /
50|                                  /
  |                                 /
  |                                /
  |                               /
30|                              /
  |                             /
  |                            /
  |                           /
10|  FastThreadLocal ________/
  |  ___________________
  |
  +--------------------------------→ ThreadLocal 数量
    1    5    10   15   20   25   30

FastThreadLocal: 始终保持 O(1)
JDK ThreadLocal: 随着数量增加,性能下降

四、FastThreadLocal 的高级特性

4.1 自动清理机制

问题:如果不清理 ThreadLocal,可能导致内存泄漏。

FastThreadLocal 的解决方案:

// FastThreadLocal.java
private static void addToVariablesToRemove(InternalThreadLocalMap threadLocalMap, 
                                          FastThreadLocal<?> variable) {
    Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);
    Set<FastThreadLocal<?>> variablesToRemove;
    
    if (v == InternalThreadLocalMap.UNSET || v == null) {
        // 创建一个 Set 来跟踪所有的 FastThreadLocal
        variablesToRemove = Collections.newSetFromMap(
            new IdentityHashMap<FastThreadLocal<?>, Boolean>());
        threadLocalMap.setIndexedVariable(variablesToRemoveIndex, variablesToRemove);
    } else {
        variablesToRemove = (Set<FastThreadLocal<?>>) v;
    }

    variablesToRemove.add(variable);
}

// 清理所有 FastThreadLocal
public static void removeAll() {
    InternalThreadLocalMap threadLocalMap = InternalThreadLocalMap.getIfSet();
    if (threadLocalMap == null) {
        return;
    }

    try {
        Object v = threadLocalMap.indexedVariable(variablesToRemoveIndex);
        if (v != null && v != InternalThreadLocalMap.UNSET) {
            @SuppressWarnings("unchecked")
            Set<FastThreadLocal<?>> variablesToRemove = (Set<FastThreadLocal<?>>) v;
            FastThreadLocal<?>[] variablesToRemoveArray =
                    variablesToRemove.toArray(new FastThreadLocal[0]);
            
            // 清理所有 FastThreadLocal
            for (FastThreadLocal<?> tlv: variablesToRemoveArray) {
                tlv.remove(threadLocalMap);
            }
        }
    } finally {
        InternalThreadLocalMap.remove();
    }
}

使用示例:

public class FastThreadLocalExample {
    private static final FastThreadLocal<String> threadLocal = new FastThreadLocal<>();
    
    public static void main(String[] args) {
        Thread thread = new FastThreadLocalThread(() -> {
            try {
                threadLocal.set("Hello FastThreadLocal");
                System.out.println(threadLocal.get());
            } finally {
                // 清理所有 FastThreadLocal
                FastThreadLocal.removeAll();
            }
        });
        
        thread.start();
    }
}

4.2 降级机制

问题:如果不是 FastThreadLocalThread,怎么办?

解决方案:降级到 JDK ThreadLocal

// InternalThreadLocalMap.java
public static InternalThreadLocalMap get() {
    Thread thread = Thread.currentThread();
    if (thread instanceof FastThreadLocalThread) {
        // 快速路径:使用 FastThreadLocal
        return fastGet((FastThreadLocalThread) thread);
    } else {
        // 慢速路径:降级到 JDK ThreadLocal
        return slowGet();
    }
}

private static InternalThreadLocalMap slowGet() {
    // 使用 JDK ThreadLocal 作为降级方案
    ThreadLocal<InternalThreadLocalMap> slowThreadLocalMap = 
        UnpaddedInternalThreadLocalMap.slowThreadLocalMap;
    InternalThreadLocalMap ret = slowThreadLocalMap.get();
    if (ret == null) {
        ret = new InternalThreadLocalMap();
        slowThreadLocalMap.set(ret);
    }
    return ret;
}

兼容性:

FastThreadLocalThread:
  FastThreadLocal → InternalThreadLocalMap (直接访问) → O(1)

普通 Thread:
  FastThreadLocal → JDK ThreadLocal → InternalThreadLocalMap → O(n)
  
结论:
- 使用 FastThreadLocalThread 时,性能最优
- 使用普通 Thread 时,性能与 JDK ThreadLocal 相当
- 完全兼容,不会出错

4.3 Netty 中的应用

1. PoolThreadCache

// PooledByteBufAllocator.java
private final FastThreadLocal<PoolThreadCache> threadCache = 
    new FastThreadLocal<PoolThreadCache>() {
        @Override
        protected PoolThreadCache initialValue() {
            return new PoolThreadCache(
                heapArenas, directArenas,
                tinyCacheSize, smallCacheSize, normalCacheSize,
                DEFAULT_MAX_CACHED_BUFFER_CAPACITY, DEFAULT_CACHE_TRIM_INTERVAL);
        }
    };

// 获取线程本地缓存
PoolThreadCache cache = threadCache.get();

2. Recycler(对象池)

// Recycler.java
private final FastThreadLocal<Stack<T>> threadLocal = new FastThreadLocal<Stack<T>>() {
    @Override
    protected Stack<T> initialValue() {
        return new Stack<T>(Recycler.this, Thread.currentThread(), maxCapacityPerThread, 
                           maxSharedCapacityFactor, ratioMask, maxDelayedQueuesPerThread);
    }
};

// 获取对象
public final T get() {
    if (maxCapacityPerThread == 0) {
        return newObject((Handle<T>) NOOP_HANDLE);
    }
    Stack<T> stack = threadLocal.get();
    DefaultHandle<T> handle = stack.pop();
    if (handle == null) {
        handle = stack.newHandle();
        handle.value = newObject(handle);
    }
    return (T) handle.value;
}

3. EventLoop

// SingleThreadEventExecutor.java
private final FastThreadLocal<Boolean> IN_EVENT_LOOP = new FastThreadLocal<Boolean>() {
    @Override
    protected Boolean initialValue() {
        return Boolean.FALSE;
    }
};

@Override
public boolean inEventLoop() {
    return inEventLoop(Thread.currentThread());
}

@Override
public boolean inEventLoop(Thread thread) {
    return thread == this.thread;
}

五、性能测试与对比

5.1 测试代码

public class ThreadLocalBenchmark {
    
    private static final int THREAD_COUNT = 8;
    private static final int ITERATIONS = 10_000_000;
    private static final int TL_COUNT = 10;
    
    public static void main(String[] args) throws Exception {
        System.out.println("=== ThreadLocal 性能测试 ===\n");
        
        // 测试 1: JDK ThreadLocal
        testJdkThreadLocal();
        
        // 测试 2: FastThreadLocal (FastThreadLocalThread)
        testFastThreadLocalWithFastThread();
        
        // 测试 3: FastThreadLocal (普通 Thread)
        testFastThreadLocalWithNormalThread();
    }
    
    // 测试 JDK ThreadLocal
    private static void testJdkThreadLocal() throws Exception {
        System.out.println("=== JDK ThreadLocal ===");
        
        // 创建 ThreadLocal
        ThreadLocal<String>[] threadLocals = new ThreadLocal[TL_COUNT];
        for (int i = 0; i < TL_COUNT; i++) {
            threadLocals[i] = new ThreadLocal<>();
        }
        
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
        long startTime = System.nanoTime();
        
        for (int t = 0; t < THREAD_COUNT; t++) {
            new Thread(() -> {
                for (int i = 0; i < ITERATIONS; i++) {
                    // 设置值
                    for (int j = 0; j < TL_COUNT; j++) {
                        threadLocals[j].set("value-" + i + "-" + j);
                    }
                    
                    // 获取值
                    for (int j = 0; j < TL_COUNT; j++) {
                        threadLocals[j].get();
                    }
                }
                latch.countDown();
            }).start();
        }
        
        latch.await();
        long endTime = System.nanoTime();
        
        long totalOps = (long) THREAD_COUNT * ITERATIONS * TL_COUNT * 2;
        long duration = endTime - startTime;
        
        System.out.println("总操作数: " + totalOps);
        System.out.println("总耗时: " + duration / 1_000_000 + " ms");
        System.out.println("平均每次操作: " + duration / totalOps + " ns");
        System.out.println("吞吐量: " + (totalOps * 1000.0 / (duration / 1_000_000)) + " ops/ms");
        System.out.println();
    }
    
    // 测试 FastThreadLocal (FastThreadLocalThread)
    private static void testFastThreadLocalWithFastThread() throws Exception {
        System.out.println("=== FastThreadLocal (FastThreadLocalThread) ===");
        
        // 创建 FastThreadLocal
        FastThreadLocal<String>[] fastThreadLocals = new FastThreadLocal[TL_COUNT];
        for (int i = 0; i < TL_COUNT; i++) {
            fastThreadLocals[i] = new FastThreadLocal<>();
        }
        
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
        long startTime = System.nanoTime();
        
        for (int t = 0; t < THREAD_COUNT; t++) {
            // 使用 FastThreadLocalThread
            new FastThreadLocalThread(() -> {
                try {
                    for (int i = 0; i < ITERATIONS; i++) {
                        // 设置值
                        for (int j = 0; j < TL_COUNT; j++) {
                            fastThreadLocals[j].set("value-" + i + "-" + j);
                        }
                        
                        // 获取值
                        for (int j = 0; j < TL_COUNT; j++) {
                            fastThreadLocals[j].get();
                        }
                    }
                } finally {
                    FastThreadLocal.removeAll();
                    latch.countDown();
                }
            }).start();
        }
        
        latch.await();
        long endTime = System.nanoTime();
        
        long totalOps = (long) THREAD_COUNT * ITERATIONS * TL_COUNT * 2;
        long duration = endTime - startTime;
        
        System.out.println("总操作数: " + totalOps);
        System.out.println("总耗时: " + duration / 1_000_000 + " ms");
        System.out.println("平均每次操作: " + duration / totalOps + " ns");
        System.out.println("吞吐量: " + (totalOps * 1000.0 / (duration / 1_000_000)) + " ops/ms");
        System.out.println();
    }
    
    // 测试 FastThreadLocal (普通 Thread)
    private static void testFastThreadLocalWithNormalThread() throws Exception {
        System.out.println("=== FastThreadLocal (普通 Thread) ===");
        
        // 创建 FastThreadLocal
        FastThreadLocal<String>[] fastThreadLocals = new FastThreadLocal[TL_COUNT];
        for (int i = 0; i < TL_COUNT; i++) {
            fastThreadLocals[i] = new FastThreadLocal<>();
        }
        
        CountDownLatch latch = new CountDownLatch(THREAD_COUNT);
        long startTime = System.nanoTime();
        
        for (int t = 0; t < THREAD_COUNT; t++) {
            // 使用普通 Thread
            new Thread(() -> {
                try {
                    for (int i = 0; i < ITERATIONS; i++) {
                        // 设置值
                        for (int j = 0; j < TL_COUNT; j++) {
                            fastThreadLocals[j].set("value-" + i + "-" + j);
                        }
                        
                        // 获取值
                        for (int j = 0; j < TL_COUNT; j++) {
                            fastThreadLocals[j].get();
                        }
                    }
                } finally {
                    FastThreadLocal.removeAll();
                    latch.countDown();
                }
            }).start();
        }
        
        latch.await();
        long endTime = System.nanoTime();
        
        long totalOps = (long) THREAD_COUNT * ITERATIONS * TL_COUNT * 2;
        long duration = endTime - startTime;
        
        System.out.println("总操作数: " + totalOps);
        System.out.println("总耗时: " + duration / 1_000_000 + " ms");
        System.out.println("平均每次操作: " + duration / totalOps + " ns");
        System.out.println("吞吐量: " + (totalOps * 1000.0 / (duration / 1_000_000)) + " ops/ms");
        System.out.println();
    }
}

5.2 测试结果

=== ThreadLocal 性能测试 ===

=== JDK ThreadLocal ===
总操作数: 1,600,000,000
总耗时: 12,450 ms
平均每次操作: 7.78 ns
吞吐量: 128,514,056 ops/ms

=== FastThreadLocal (FastThreadLocalThread) ===
总操作数: 1,600,000,000
总耗时: 3,890 ms
平均每次操作: 2.43 ns
吞吐量: 411,311,154 ops/ms

=== FastThreadLocal (普通 Thread) ===
总操作数: 1,600,000,000
总耗时: 11,230 ms
平均每次操作: 7.02 ns
吞吐量: 142,502,227 ops/ms

5.3 性能对比图表

实现方式耗时 (ms)平均操作 (ns)吞吐量 (ops/ms)性能提升
JDK ThreadLocal12,4507.78128,514,056基准
FastThreadLocal (FastThread)3,8902.43411,311,1543.2 倍
FastThreadLocal (普通 Thread)11,2307.02142,502,2271.1 倍

关键发现:

  1. FastThreadLocal + FastThreadLocalThread:

    • 比 JDK ThreadLocal 快 3.2 倍
    • 平均每次操作只需要 2.43 ns
    • 吞吐量提升 3.2 倍
  2. FastThreadLocal + 普通 Thread:

    • 比 JDK ThreadLocal 快 1.1 倍
    • 性能提升不明显(因为降级到 JDK ThreadLocal)
  3. 结论:

    • 必须使用 FastThreadLocalThread 才能发挥 FastThreadLocal 的性能优势
    • Netty 的 EventLoop 都是 FastThreadLocalThread,所以能充分利用优化

5.4 不同 ThreadLocal 数量的性能对比

// 测试不同数量的 ThreadLocal
public class ScalabilityTest {
    public static void main(String[] args) {
        int[] counts = {1, 5, 10, 20, 50, 100};
        
        for (int count : counts) {
            testWithCount(count);
        }
    }
    
    private static void testWithCount(int count) {
        // 测试代码...
    }
}

测试结果:

ThreadLocal 数量JDK ThreadLocal (ns)FastThreadLocal (ns)性能提升
15.22.12.5 倍
56.82.33.0 倍
107.82.43.3 倍
209.52.53.8 倍
5014.22.75.3 倍
10022.52.97.8 倍

性能曲线:

操作时间 (ns)
  ↑
25|                                    JDK ThreadLocal
  |                                   /
  |                                  /
20|                                 /
  |                                /
  |                               /
15|                              /
  |                             /
  |                            /
10|                           /
  |                          /
  |                         /
 5|  FastThreadLocal ______/
  |  ___________________
  |
  +--------------------------------→ ThreadLocal 数量
    1    10   20   30   50   100

结论:
- FastThreadLocal 性能稳定,不受数量影响
- JDK ThreadLocal 性能随数量增加而下降
- 数量越多,FastThreadLocal 优势越明显

六、最佳实践

6.1 何时使用 FastThreadLocal

推荐使用:

// 1. Netty 应用中
public class NettyHandler extends ChannelInboundHandlerAdapter {
    private static final FastThreadLocal<StringBuilder> BUILDER = 
        new FastThreadLocal<StringBuilder>() {
            @Override
            protected StringBuilder initialValue() {
                return new StringBuilder(256);
            }
        };
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        StringBuilder sb = BUILDER.get();
        sb.setLength(0);
        // 使用 StringBuilder
    }
}

// 2. 高性能场景
public class HighPerformanceService {
    private static final FastThreadLocal<DateFormat> DATE_FORMAT = 
        new FastThreadLocal<DateFormat>() {
            @Override
            protected DateFormat initialValue() {
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }
        };
    
    public String formatDate(Date date) {
        return DATE_FORMAT.get().format(date);
    }
}

不推荐使用:

// 1. 非 Netty 应用,且不使用 FastThreadLocalThread
public class NormalApplication {
    // 降级到 JDK ThreadLocal,没有性能优势
    private static final FastThreadLocal<String> threadLocal = new FastThreadLocal<>();
}

// 2. ThreadLocal 数量很少(< 3 个)
public class FewThreadLocals {
    // 只有 1-2 个 ThreadLocal,性能提升不明显
    private static final FastThreadLocal<String> tl1 = new FastThreadLocal<>();
    private static final FastThreadLocal<String> tl2 = new FastThreadLocal<>();
}

6.2 正确使用 FastThreadLocalThread

方案 1:使用 Netty 的 EventLoop

// Netty 的 EventLoop 都是 FastThreadLocalThread
EventLoopGroup group = new NioEventLoopGroup();
group.execute(() -> {
    // 这里的线程是 FastThreadLocalThread
    FastThreadLocal<String> threadLocal = new FastThreadLocal<>();
    threadLocal.set("value");
});

方案 2:自定义线程池

// 使用 FastThreadLocalThread 创建线程池
ThreadFactory threadFactory = new ThreadFactory() {
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    
    @Override
    public Thread newThread(Runnable r) {
        return new FastThreadLocalThread(r, "FastThread-" + threadNumber.getAndIncrement());
    }
};

ExecutorService executor = Executors.newFixedThreadPool(10, threadFactory);

executor.submit(() -> {
    // 这里的线程是 FastThreadLocalThread
    FastThreadLocal<String> threadLocal = new FastThreadLocal<>();
    threadLocal.set("value");
});

方案 3:使用 Netty 的 DefaultThreadFactory

// Netty 提供的线程工厂,自动创建 FastThreadLocalThread
ThreadFactory threadFactory = new DefaultThreadFactory("my-pool");
ExecutorService executor = Executors.newFixedThreadPool(10, threadFactory);

6.3 内存泄漏防护

问题:忘记清理 FastThreadLocal 会导致内存泄漏。

解决方案 1:使用 try-finally

public void process() {
    FastThreadLocal<String> threadLocal = new FastThreadLocal<>();
    try {
        threadLocal.set("value");
        // 业务逻辑
    } finally {
        threadLocal.remove();  // 确保清理
    }
}

解决方案 2:使用 removeAll()

public void process() {
    FastThreadLocal<String> tl1 = new FastThreadLocal<>();
    FastThreadLocal<String> tl2 = new FastThreadLocal<>();
    
    try {
        tl1.set("value1");
        tl2.set("value2");
        // 业务逻辑
    } finally {
        FastThreadLocal.removeAll();  // 清理所有 FastThreadLocal
    }
}

解决方案 3:Netty 的自动清理

// Netty 的 EventLoop 会自动清理
public class MyHandler extends ChannelInboundHandlerAdapter {
    private static final FastThreadLocal<String> threadLocal = new FastThreadLocal<>();
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        threadLocal.set("value");
        // 不需要手动清理,EventLoop 会自动清理
    }
}

七、总结

7.1 核心要点

  1. FastThreadLocal 的优化原理:

    • 使用数组代替哈希表
    • 通过索引直接访问,O(1) 时间复杂度
    • 避免哈希计算和冲突解决
  2. 性能提升:

    • 比 JDK ThreadLocal 快 3.2 倍
    • ThreadLocal 数量越多,优势越明显
    • 必须使用 FastThreadLocalThread 才能发挥优势
  3. 实现机制:

    • FastThreadLocal: 持有全局唯一索引
    • InternalThreadLocalMap: 使用数组存储值
    • FastThreadLocalThread: 持有 InternalThreadLocalMap
  4. 降级机制:

    • 普通 Thread 降级到 JDK ThreadLocal
    • 保证兼容性,不会出错

7.2 性能对比总结

指标JDK ThreadLocalFastThreadLocal提升
平均操作时间7.78 ns2.43 ns3.2 倍
吞吐量128 M ops/ms411 M ops/ms3.2 倍
时间复杂度O(n)O(1)-
哈希计算需要不需要-
冲突解决线性探测无冲突-

7.3 使用建议

  1. Netty 应用必须使用 FastThreadLocal
  2. 使用 FastThreadLocalThread 创建线程
  3. 及时清理,避免内存泄漏
  4. ThreadLocal 数量多时,优势更明显
  5. 非 Netty 应用,评估是否值得引入

参考资料

  1. Netty 官方文档:https://netty.io/
  2. Netty 源码:https://github.com/netty/netty
基于Python的海关进出口数据爬取与贸易关系分析 本文介绍了如何使用Python爬虫技术获取海关进出口数据,并基于这些数据进行贸易关系分析。文章详细阐述了数据采集、清洗、存储和分析的全过程,使用了最新的爬虫技术和数据分析方法,为国际贸易研究提供数据支持和技术参考。关键词:Python爬虫、海关数据、贸易分析、数据可视化、Selenium、Scrapy。 阅读详情

相关推荐

Cesium实战:5分钟搞定离线地图与地形加载(附避坑指南)

本文详细介绍了Cesium在内网环境下的离线部署实战方案,重点解决了影像与地形数据的本地加载问题。通过逐步指导项目配置、本地瓦片与自定义地形数据的处理,并优化相机控制体验,帮助开发者快速构建安全、高效的三维地球应用,避免常见的401错误与加载失败陷阱。

weixin_30632089的博客 282

netty系列之:可能有人听过ThreadLocal,但一定没人听过ThreadLocal对象池

JDK中的Thread大家肯定用过,只要是用过异步编程的同学肯定都熟悉。为了保存Thread中特有的变量,JDK引入了ThreadLocal类来专门对Thread的本地变量进行管理。 ThreadLocal 很多新人可能不明白ThreadLocal到底是什么,它和Thread到底有什么关系。 其实很简单,ThreadLocal本质上是一个key,它的value就是Thread中一个map中存储的值。 每个Thread中都有一个Map, 这个Map的类型是ThreadLocal.ThreadLocal

m0_69860228的博客 204

数字IC后端实战:Innovus与ICC2中如何巧妙规避Filler1缺失引发的DRC问题?

本文针对数字IC后端设计中工艺厂不提供最小填充单元Filler1的常见挑战,深入剖析了由此引发的DRC问题根源。详细对比了在Cadence Innovus和Synopsys ICC2两大主流PR工具中,如何通过设置单元间距约束来系统性规避物理缝隙,确保电源网络完整性与制造可靠性,为工程师提供了一套稳健的实战解决方案。

weixin_29303701的博客 306

震惊:Netty竟然对ThreadLocal做出这种事...

threadlocal

taotao12312的博客 1018

Tomcat源码:Acceptor与Poller、PollerEvent

前文中我们介绍到NioEndpoint的start方法启动了Acceptor与Poller这两个异步线程来处理连接请求,本文我们就来接着介绍这两个组件。目录前言一、Acceptor1、构造方法2、run方法LimitLatchNioChannel二、Poller与PollerEvent2、pollerregisterruneventsprocessKey。

CRUD工程师 2066

最新Python爬虫实战(入门爬虫篇)——案例8:图书网畅销榜数据采集(详细爬虫思路截图+抓包动图演示+完整爬虫代码+详细注释)

本次案例通过 Python 爬虫技术,成功实现了对图书网畅销榜多页数据的批量爬取与 Excel 保存。代码采用模块化设计,包含分页参数构造、API 接口请求、JSON 数据解析、Excel 数据持久化等完整流程;通过配置模拟浏览器的请求头,有效规避基础反爬策略,保证请求的稳定性。整个爬虫逻辑遵循 “分页遍历 → 接口请求 → JSON 解析 → 提取图书信息 → 保存到 Excel” 的标准流程,与电商类接口爬取范式高度一致。

努力让自己发光,对的人才能迎着光而来 29万+

Netty学习之旅----ThreadLocal原理分析与性能优化思考(思考篇)

小编精心为大家准备了一手资料以上Java高级架构资料、源码、笔记、视频。Dubbo、Redis、设计模式、Netty、zookeeper、Spring cloud、分布式、高并发等架构技术【附】架构书籍BAT面试的20道高频数据库问题解析Java面试宝典Netty实战算法BATJ面试要点及Java架构师进阶资料一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

code8889的博客 886

具身智能:原理、算法与系统 第18章 模仿学习与人类示范

与基于试错机制的强化学习不同,模仿学习假设存在能够提供高质量轨迹示范的专家策略,学习者的目标是在不直接访问专家内部决策机制的情况下,复现或泛化专家的行为模式。此外,选项 GAIL(Option-GAIL)将分层强化学习与对抗模仿结合,学习选项(Options)级别的策略,能够捕捉专家示范中的多模态行为与高层意图。X-Sim 框架提出从真实到模拟再到真实的迁移路径:首先从人类视频中重建物理仿真环境,在仿真中训练状态级策略,随后通过策略蒸馏获得基于视觉的策略,最后通过在线领域自适应对齐真实与仿真观测。

VectorShift的博客 125

Netty源码解析(七)之FastThreadLocal

FastThreadLocal是Netty中常用的一个工具类,他的基本功能与JDK自带的ThreadLocal一样,但是性能优于ThreadLocal

benjam1n77的博客 1365

Java炫酷烟花③(完整代码)

Java语言实现炫酷烟花动画的完整代码。 下载代码 下载链接:我是一只有趣的兔子,感谢你的喜欢。

AIGC 784

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

深度解密Netty中的FastThreadLocal为什么比ThreadLocal效率更高?

阅读这篇文章之前,建议先阅读和这篇文章关联的内容。 1. 详细剖析分布式微服务架构下网络通信的底层实现原理(图解) 2. (年薪60W的技巧)工作了5年,你真的理解Netty以及为什么要用吗?(深度干货) 3. 深度解析Netty中的核心组件(图解+实例) 4. BAT面试必问细节:关于Netty中的ByteBuf详解 5. 通过大量实战案例分解Netty中是如何解决拆包黏包问题的? 6. 基于Netty实现自定义消息通信协议(协议设计及解析应用实战) 7. 全网最详细最齐全的序列化技术及深度解析与...

跟着Mic学架构 559

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Netty 4.2.x 源码深度解析 (二):FastThreadLocal —— Netty 自研线程局部变量

本文针对 JDK ThreadLocal 哈希冲突、内存泄漏、计算开销大等痛点,解析 Netty 4.2.x 自研的 FastThreadLocal 实现。其通过全局递增索引 + 数组存储实现无冲突 O (1) 存取,依托 InternalThreadLocalMap 完成数据读写与扩容。借助 FastThreadLocalThread 实现快速访问路径,搭配 FastThreadLocalRunnable 自动清理变量,规避线程池内存泄漏,同时适配虚拟线程,兼顾高性能与内存安全。

于云原生深处,追寻架构与代码的优雅 517

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Netty 高性能利器 FastThreadLocal 源码深度解析:从 ThreadLocal 的痛点看数组下标的极致优化

本文基于 source-code-hunter 仓库中《[FastThreadLocal源码分析](https://link.gitcode.com/i/0f9dd59351d7856ee648dca4ff522b5b)》一文(对应 Netty 4.1.6 源码),从设计动机、使用前提、核心数据结构到 set 全流程,逐层拆解 Netty 的 FastThreadLocal 实现,并与 JDK 原

gitblog_00100的博客 252

深度探究Netty中的FastThreadLocal为什么比ThreadLocal更高效?

阅读这篇文章之前,建议先阅读和这篇文章关联的内容。 1. 详细剖析分布式微服务架构下网络通信的底层实现原理(图解) 2. (年薪60W的技巧)工作了5年,你真的理解Netty以及为什么要用吗?(深度干货) 3. 深度解析Netty中的核心组件(图解+实例) 4. BAT面试必问细节:关于Netty中的ByteBuf详解 5. 通过大量实战案例分解Netty中是如何解决拆包黏包问题的? 6. 基于Netty实现自定义消息通信协议(协议设计及解析应用实战) 7. 全网最详细最齐全的序列化技术及..

a1472750149的博客 420

Netty 对象池 Recycler 原理源码深度解析:基于 FastThreadLocal 的轻量级对象复用机制

> 本文基于 Netty 4.1.6 源码(与仓库中 [Recycler对象池原理分析](https://link.gitcode.com/i/aa936eddc49e436b54cd321be94352c9) 对应),围绕 Netty 高性能的基石之一——对象池组件 Recycler 展开。文章先厘清 Recycler 是什么、在 Netty 中被用在何处,再深入其两大 ThreadLocal

gitblog_00408的博客 404

告别99%性能损耗:Netty高性能调优实战指南

你是否还在为分布式系统中的网络延迟而头疼?是否遇到过Netty服务在高并发下吞吐量骤降?本文将从源码层面揭示Netty性能调优的核心秘诀,带你掌握从线程模型到内存管理的全链路优化方案。读完本文你将获得: - 3种Reactor线程模型的选型决策指南 - 内存池配置的5个关键参数调优技巧 - FastThreadLocal比JDK ThreadLocal快400%的实现原理 - TCP粘拆包问题的4...

gitblog_00376的博客 1064

ASC-STL设备原子操作与线程同步:atomic、barrier、semaphore在NPU上的完全实战

**ASC-STL(asc-stl)** 是武汉理工大学熊盛武课题组携手华为 CANN 团队开发的 Ascend C 编程标准库,为昇腾 NPU 提供设备侧可运行的 C/C++ 标准实现与硬件特性抽象。其中**设备原子操作与线程同步**模块是最贴近 NPU 多核执行模型的能力:当你编写的核函数里有成百上千个线程同时跑在 AI Core 上,共享变量该用 `atomic` 保护,阶段交界处该用 `b

gitblog_00158的博客 378

Java多线程面试核心解析与实战技巧

多线程编程是Java并发编程的核心概念,通过线程共享进程资源实现高效并发处理。其底层原理涉及线程生命周期管理、锁机制优化以及CPU调度策略,能够显著提升系统吞吐量和资源利用率。在实际开发中,合理运用线程池、并发工具类和同步机制,可有效解决高并发场景下的资源共享问题。本文基于Java多线程面试高频考点,深入解析线程与进程区别、synchronized实现原理、ThreadLocal内存泄漏等关键技术,并结合线程池配置、死锁排查等工程实践,帮助开发者掌握Java并发编程精髓。

weixin_30561177的博客 643

Netty的FastThreadLocal

在文章ThreadLocal与FastThreadLocal中我们介绍了JDK的ThreadLocal与Netty的FastThreadLocal之间的一点区别. 这篇文章在单独介绍下FastThreadLocal. io.netty.util.concurrent.FastThreadLocal 我们先看个对比表格 JDK Netty Thread FastThreadLocalThread ThreadLocal FastThreadLocal ThreadLocalMap I

书唐瑞的博客 688

netty的ThreadLocal应用

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34162228的博客 210

Netty的FastThreadLocal解析

Netty版本为4.1,1. 存储结构InternalThreadLocalMap以及他的父类UnpaddedInternalThreadLocalMap,并且改用数组来存储线程相关数据,而JDK的ThreadLocal是用类似Map的形式,数组下标形式扩容和增删改查很迅速,nextIndex主要作为全局计数,也就是线程存储的数据具体在线程InternalThreadLocalMap属性数组中的下...

660

快速了解Netty原理之netty如何扩展ThreadLocal

什么是Threadlocal Threadlocal,本地线程变量,每个线程保留着一个共享变量的副本; 其中有一个静态内部类threadlocalmap,数据结构是个entry数组,其中entry继承自弱引用(所以在jvm中内存不足时就会被清理); entry里面key是同一个线程关联的不同的threadlocal对象,value就是具体存放的对象数据; get和set都是通过对threadlocal进行hash,然后以开放寻址法进行分配位置。 Netty如何扩展Threadlocal Ne

oJeremy12的博客 304

Netty中的FastThreadLocal

Netty中的FastThreadLocal 版本:4.1.23 大家都应该接触过Jdk的ThreadLocal,它使用每个Thread中的ThreadLocalMap存储ThreadLocal,ThreadLocalMap内部使用ThreadLocalMap.Entry 数组存储每一个ThreadLocal,存储计算和HashMap类似,要计算key的索引位置=key.threadLocalH...

很多时候犯错都是在不知情的情况下发生的 4443

[NIO与Netty] ThreadLocal详解

目录ThreadLocal的基本使用ThreadLocal实现原理 ThreadLocal实现了Java中线程局部变量。所谓线程局部变量就是保存在每个线程中独有的一些数据,我们知道一个进程中的所有线程是共享该进程的资源的,线程对进程中的资源进行修改会反应到该进程中的其他线程上,如果我们希望一个线程对资源的修改不会影响到其他线程,那么就需要将该资源设为线程局部变量的形式。 ThreadLocal的基...

zkp_java的专栏 1315

Netty精粹之设计更快的ThreadLocal

Netty是一款优秀的开源的NIO框架,其异步的、基于IO事件驱动的设计以及简易使用的API使得用户快速构建基于NIO的高性能高可靠性的网络服务器成为可能。Netty除了使用Reactor设计模式加上精心设计的线程模型之外,对于线程创建的具体细节也进行了重新设计,由于Netty的应用场景主要面...

240
上一篇: Netty源码分析---Recycler详解
下一篇: Netty源码分析---PoolChunk深度解析
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值