Netty源码分析---Recycler详解

Netty源码分析(七)—Recycler对象池分析 Netty源码分析(七)—Recycler对象池分析 Netty中实现轻量级的对象池技术,用来减少因为频繁的对象创建销毁而触发的内存分配和GC带来的性能消耗;Recycler是netty轻量级对象池的具体实现; Netty使用ThreadLocal变量实现对象池的线程隔离进而实现对象池的无锁线程安全,相当于每个线程都维护着各自的小线程池 个人主页:tuzhenyu’s 阅读详情

好的!Recycler 是 Netty 的轻量级对象池实现,我详细讲解它的原理。

Recycler 类的核心结构

public abstract class Recycler<T> {
    
    // 线程本地的对象栈
    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);
        }
    };
    
    // 每个线程最多缓存多少个对象
    private final int maxCapacityPerThread;
    
    // 其他配置参数
    private final int maxSharedCapacityFactor;
    private final int ratioMask;
    private final int maxDelayedQueuesPerThread;
    
    // 抽象方法,由子类实现,用于创建新对象
    protected abstract T newObject(Handle<T> handle);
}

一、核心概念

1. Handle(句柄)

public interface Handle<T> {
    void recycle(T object);
}

Handle 的作用:

  • 每个对象都有一个 Handle
  • Handle 记录对象属于哪个 Stack
  • 通过 Handle 可以将对象归还到对象池

DefaultHandle 实现:

static final class DefaultHandle<T> implements Handle<T> {
    private int lastRecycledId;
    private int recycleId;
    
    boolean hasBeenRecycled;
    
    private Stack<?> stack;
    private Object value;  // 实际的对象
    
    DefaultHandle(Stack<?> stack) {
        this.stack = stack;
    }
    
    @Override
    public void recycle(Object object) {
        if (object != value) {
            throw new IllegalArgumentException("object does not belong to handle");
        }
        
        Stack<?> stack = this.stack;
        if (lastRecycledId != recycleId || stack == null) {
            throw new IllegalStateException("recycled already");
        }
        
        stack.push(this);  // 归还到栈
    }
}

2. Stack(对象栈)

static final class Stack<T> {
    final Recycler<T> parent;
    final Thread thread;
    
    // 存储对象的数组
    DefaultHandle<?>[] elements;
    
    // 栈顶指针
    int size;
    
    // 最大容量
    private final int maxCapacity;
    
    // 其他线程归还的对象队列
    private volatile WeakOrderQueue head;
    
    Stack(Recycler<T> parent, Thread thread, int maxCapacity, ...) {
        this.parent = parent;
        this.thread = thread;
        this.maxCapacity = maxCapacity;
        
        // 初始化数组
        elements = new DefaultHandle[min(INITIAL_CAPACITY, maxCapacity)];
    }
}

Stack 的结构:

Stack:
  elements = [Handle1, Handle2, Handle3, null, null, ...]
              ↑       ↑       ↑
            size = 3
            
  maxCapacity = 4096(默认)

二、get() 方法详解

public final T get() {
    if (maxCapacityPerThread == 0) {
        // 不使用对象池,直接创建
        return newObject((Handle<T>) NOOP_HANDLE);
    }
    
    // 获取当前线程的 Stack
    Stack<T> stack = threadLocal.get();
    
    // 从栈中弹出一个 Handle
    DefaultHandle<T> handle = stack.pop();
    
    if (handle == null) {
        // 栈为空,创建新对象
        handle = stack.newHandle();
        handle.value = newObject(handle);
    }
    
    return (T) handle.value;
}

步骤1:获取 Stack

Stack<T> stack = threadLocal.get();

第一次调用时:

  • 触发 initialValue()
  • 创建新的 Stack
  • 绑定到当前线程

后续调用:

  • 直接返回已创建的 Stack

步骤2:从 Stack 弹出对象

DefaultHandle<T> handle = stack.pop();

Stack.pop() 方法:

DefaultHandle<T> pop() {
    int size = this.size;
    if (size == 0) {
        // 栈为空,尝试从其他线程的队列获取
        if (!scavenge()) {
            return null;
        }
        size = this.size;
    }
    
    // 弹出栈顶元素
    size --;
    DefaultHandle ret = elements[size];
    elements[size] = null;
    
    if (ret.lastRecycledId != ret.recycleId) {
        throw new IllegalStateException("recycled multiple times");
    }
    
    ret.recycleId = 0;
    ret.lastRecycledId = 0;
    this.size = size;
    
    return ret;
}

执行过程:

假设 Stack 状态:
elements = [Handle1, Handle2, Handle3, null, ...]
size = 3

执行 pop():
1. size = 3,不为 0
2. size-- → size = 2
3. ret = elements[2] → Handle3
4. elements[2] = null
5. 重置 Handle3 的状态
6. this.size = 2
7. 返回 Handle3

结果:
elements = [Handle1, Handle2, null, null, ...]
size = 2

如果栈为空:

elements = [null, null, null, ...]
size = 0

执行 pop():
1. size == 0
2. scavenge() → 尝试从其他线程的队列获取
   ├─ 成功:size > 0,继续弹出
   └─ 失败:返回 null

步骤3:创建新对象(如果需要)

if (handle == null) {
    handle = stack.newHandle();
    handle.value = newObject(handle);
}

stack.newHandle() 方法:

DefaultHandle<T> newHandle() {
    return new DefaultHandle<T>(this);
}

newObject(handle) 方法:

这是抽象方法,由子类实现:

// PooledUnsafeDirectByteBuf 中的实现
private static final Recycler<PooledUnsafeDirectByteBuf> RECYCLER = 
    new Recycler<PooledUnsafeDirectByteBuf>() {
        @Override
        protected PooledUnsafeDirectByteBuf newObject(Handle<PooledUnsafeDirectByteBuf> handle) {
            return new PooledUnsafeDirectByteBuf(handle, 0);
        }
    };

PooledUnsafeDirectByteBuf 构造函数:

PooledUnsafeDirectByteBuf(Handle<PooledUnsafeDirectByteBuf> recyclerHandle, int maxCapacity) {
    super(recyclerHandle, maxCapacity);
}

// PooledByteBuf 构造函数
protected PooledByteBuf(Recycler.Handle<? extends PooledByteBuf<T>> recyclerHandle, int maxCapacity) {
    super(maxCapacity);
    this.recyclerHandle = (Handle<PooledByteBuf<T>>) recyclerHandle;
}

关键点:

  • ByteBuf 保存了 recyclerHandle
  • 后续可以通过 handle 归还对象

步骤4:返回对象

return (T) handle.value;

handle.value 就是实际的 ByteBuf 对象。


三、recycle() 方法详解(归还对象)

// 用户调用
buf.release();

// 最终调用
recyclerHandle.recycle(this);

Handle.recycle() 方法:

@Override
public void recycle(Object object) {
    if (object != value) {
        throw new IllegalArgumentException("object does not belong to handle");
    }
    
    Stack<?> stack = this.stack;
    if (lastRecycledId != recycleId || stack == null) {
        throw new IllegalStateException("recycled already");
    }
    
    stack.push(this);
}

Stack.push() 方法:

void push(DefaultHandle<?> item) {
    Thread currentThread = Thread.currentThread();
    
    if (thread == currentThread) {
        // 同一个线程,直接压栈
        pushNow(item);
    } else {
        // 不同线程,放入延迟队列
        pushLater(item, currentThread);
    }
}

private void pushNow(DefaultHandle<?> item) {
    if ((item.recycleId | item.lastRecycledId) != 0) {
        throw new IllegalStateException("recycled already");
    }
    
    item.recycleId = item.lastRecycledId = OWN_THREAD_ID;
    
    int size = this.size;
    if (size >= maxCapacity || dropHandle(item)) {
        // 栈满了或者被丢弃
        return;
    }
    
    if (size == elements.length) {
        // 数组满了,扩容
        elements = Arrays.copyOf(elements, min(size << 1, maxCapacity));
    }
    
    elements[size] = item;
    this.size = size + 1;
}

执行过程:

假设 Stack 状态:
elements = [Handle1, Handle2, null, null, ...]
size = 2

执行 push(Handle3):
1. 检查是否同一个线程 ✓
2. pushNow(Handle3)
3. 设置 recycleId
4. size = 2 < maxCapacity ✓
5. size < elements.length ✓
6. elements[2] = Handle3
7. this.size = 3

结果:
elements = [Handle1, Handle2, Handle3, null, ...]
size = 3

四、完整的生命周期示例

第一次分配

// 1. 获取对象
PooledUnsafeDirectByteBuf buf = RECYCLER.get();

// 执行过程:
threadLocal.get() → Stack (第一次创建)
stack.pop() → null (栈为空)
stack.newHandle() → Handle1
newObject(Handle1) → new PooledUnsafeDirectByteBuf(Handle1, 0)
Handle1.value = buf
返回 buf

// Stack 状态:
elements = [null, null, ...]
size = 0

使用和释放

// 2. 使用 ByteBuf
buf.writeInt(123);

// 3. 释放
buf.release();

// 执行过程:
buf.deallocate()
recyclerHandle.recycle(this)
Handle1.recycle(buf)
stack.push(Handle1)
pushNow(Handle1)
elements[0] = Handle1
size = 1

// Stack 状态:
elements = [Handle1, null, ...]
size = 1

第二次分配

// 4. 再次获取对象
PooledUnsafeDirectByteBuf buf2 = RECYCLER.get();

// 执行过程:
threadLocal.get() → Stack (已存在)
stack.pop() → Handle1 (从栈中弹出)
buf.reuse(maxCapacity) → 重置状态
返回 buf (复用了第一次的对象)

// Stack 状态:
elements = [null, null, ...]
size = 0

// 注意:buf2 和 buf 是同一个对象!

第三次分配(栈为空)

// 5. 第三次获取
PooledUnsafeDirectByteBuf buf3 = RECYCLER.get();

// 执行过程:
stack.pop() → null (栈为空)
stack.newHandle() → Handle2
newObject(Handle2) → new PooledUnsafeDirectByteBuf(Handle2, 0)
返回新对象

// 创建了新对象

五、跨线程回收(重点)

场景:线程 A 分配,线程 B 释放

// 线程 A
PooledUnsafeDirectByteBuf buf = RECYCLER.get();

// 将 buf 传递给线程 B

// 线程 B
buf.release();

问题:

  • buf 是从线程 A 的 Stack 获取的
  • 但在线程 B 中释放
  • 不能直接放回线程 A 的 Stack(线程不安全)

解决方案:WeakOrderQueue

void push(DefaultHandle<?> item) {
    Thread currentThread = Thread.currentThread();
    
    if (thread == currentThread) {
        // 同一个线程,直接压栈
        pushNow(item);
    } else {
        // 不同线程,放入延迟队列
        pushLater(item, currentThread);
    }
}

pushLater() 方法

private void pushLater(DefaultHandle<?> item, Thread thread) {
    // 获取或创建 WeakOrderQueue
    Map<Stack<?>, WeakOrderQueue> delayedRecycled = DELAYED_RECYCLED.get();
    WeakOrderQueue queue = delayedRecycled.get(this);
    
    if (queue == null) {
        // 创建新的队列
        if (delayedRecycled.size() >= maxDelayedQueues) {
            // 队列太多,丢弃
            delayedRecycled.put(this, WeakOrderQueue.DUMMY);
            return;
        }
        
        // 创建新队列并链接到 Stack
        if ((queue = WeakOrderQueue.allocate(this, thread)) == null) {
            return;
        }
        delayedRecycled.put(this, queue);
    } else if (queue == WeakOrderQueue.DUMMY) {
        // 已经达到上限,丢弃
        return;
    }
    
    // 将对象放入队列
    queue.add(item);
}

WeakOrderQueue 的结构:

private static final class WeakOrderQueue {
    
    // 链表节点
    private static final class Link extends AtomicInteger {
        private final DefaultHandle<?>[] elements = new DefaultHandle[LINK_CAPACITY];
        
        private int readIndex;
        private Link next;
    }
    
    private final WeakReference<Thread> owner;  // 拥有这个队列的线程
    private final int id;
    
    private Link head, tail;
    private WeakOrderQueue next;  // 下一个队列
    
    private final Stack<?> stack;  // 目标 Stack
}

跨线程回收的结构:

线程 A 的 Stack:
  elements = [Handle1, Handle2, ...]
  size = 2
  
  head → WeakOrderQueue (线程 B 的队列)
         ├─ Link1: [Handle3, Handle4, ...]
         └─ Link2: [Handle5, Handle6, ...]
         
       → WeakOrderQueue (线程 C 的队列)
         └─ Link1: [Handle7, Handle8, ...]

执行过程:

1. 线程 A 分配对象:
   buf = RECYCLER.get()
   从线程 A 的 Stack 获取

2. 线程 B 释放对象:
   buf.release()
   ├─ 检测到不是同一个线程
   ├─ 获取线程 B 的 DELAYED_RECYCLED
   ├─ 查找或创建 WeakOrderQueue
   └─ queue.add(handle)
      └─ 放入线程 B 的队列

3. 线程 A 再次分配:
   buf2 = RECYCLER.get()
   ├─ stack.pop()
   ├─ size == 0(栈为空)
   ├─ scavenge() → 从 WeakOrderQueue 转移对象
   │  ├─ 遍历 head 链表
   │  ├─ 从 WeakOrderQueue 读取对象
   │  └─ 放入 elements 数组
   ├─ size > 0
   └─ 弹出对象

scavenge() 方法

boolean scavenge() {
    // 尝试从 WeakOrderQueue 转移对象到 Stack
    if (scavengeSome()) {
        return true;
    }
    
    // 重置游标,下次从头开始
    prev = null;
    cursor = head;
    return false;
}

boolean scavengeSome() {
    WeakOrderQueue prev;
    WeakOrderQueue cursor = this.cursor;
    
    if (cursor == null) {
        prev = null;
        cursor = head;
        if (cursor == null) {
            return false;
        }
    } else {
        prev = this.prev;
    }
    
    boolean success = false;
    do {
        // 从 WeakOrderQueue 转移对象
        if (cursor.transfer(this)) {
            success = true;
            break;
        }
        
        WeakOrderQueue next = cursor.next;
        if (cursor.owner.get() == null) {
            // 线程已经结束,移除这个队列
            if (cursor.hasFinalData()) {
                for (;;) {
                    if (cursor.transfer(this)) {
                        success = true;
                    } else {
                        break;
                    }
                }
            }
            
            if (prev != null) {
                prev.next = next;
            }
        } else {
            prev = cursor;
        }
        
        cursor = next;
        
    } while (cursor != null && !success);
    
    this.prev = prev;
    this.cursor = cursor;
    return success;
}

transfer() 方法:

boolean transfer(Stack<?> dst) {
    Link head = this.head;
    if (head == null) {
        return false;
    }
    
    // 从 Link 读取对象
    if (head.readIndex == LINK_CAPACITY) {
        if (head.next == null) {
            return false;
        }
        this.head = head = head.next;
    }
    
    final int srcStart = head.readIndex;
    int srcEnd = head.get();
    final int srcSize = srcEnd - srcStart;
    
    if (srcSize == 0) {
        return false;
    }
    
    final int dstSize = dst.size;
    final int expectedCapacity = dstSize + srcSize;
    
    if (expectedCapacity > dst.elements.length) {
        // 目标数组需要扩容
        final int actualCapacity = dst.increaseCapacity(expectedCapacity);
        srcEnd = min(srcStart + actualCapacity - dstSize, srcEnd);
    }
    
    if (srcStart != srcEnd) {
        final DefaultHandle[] srcElems = head.elements;
        final DefaultHandle[] dstElems = dst.elements;
        int newDstSize = dstSize;
        
        // 批量转移
        for (int i = srcStart; i < srcEnd; i++) {
            DefaultHandle element = srcElems[i];
            if (element.recycleId == 0) {
                element.recycleId = element.lastRecycledId;
            } else if (element.recycleId != element.lastRecycledId) {
                throw new IllegalStateException("recycled already");
            }
            srcElems[i] = null;
            
            if (dst.dropHandle(element)) {
                continue;
            }
            
            element.stack = dst;
            dstElems[newDstSize++] = element;
        }
        
        if (srcEnd == LINK_CAPACITY && head.next != null) {
            this.head = head.next;
        }
        
        head.readIndex = srcEnd;
        if (dst.size == newDstSize) {
            return false;
        }
        dst.size = newDstSize;
        return true;
    } else {
        return false;
    }
}

转移过程示例:

线程 A 的 Stack:
  elements = [null, null, ...]
  size = 0
  
  head → WeakOrderQueue (线程 B)
         └─ Link: [Handle1, Handle2, Handle3, ...]

执行 scavenge():
1. cursor = head (线程 B 的队列)
2. cursor.transfer(stack)
   ├─ 从 Link 读取 Handle1, Handle2, Handle3
   ├─ 放入 Stack.elements
   └─ 返回 true

结果:
  elements = [Handle1, Handle2, Handle3, null, ...]
  size = 3

六、Recycler 的优势

1. 减少对象创建

传统方式:
for (int i = 0; i < 10000; i++) {
    ByteBuf buf = new PooledUnsafeDirectByteBuf(...);
    // 使用
    // 等待 GC
}
创建 10000 个对象

Recycler 方式:
for (int i = 0; i < 10000; i++) {
    ByteBuf buf = RECYCLER.get();
    // 使用
    buf.release();  // 归还
}
可能只创建几十个对象,其他都是复用

2. 减少 GC 压力

对象复用:
- 不需要频繁创建对象
- 不需要频繁回收对象
- GC 压力大幅降低

3. 线程本地优化

每个线程有自己的 Stack:
- 无锁访问
- 性能极高
- 缓存友好

4. 支持跨线程回收

通过 WeakOrderQueue:
- 线程 A 分配的对象
- 可以在线程 B 释放
- 最终回到线程 A 的 Stack
- 保证线程安全

总结

Recycler 的核心机制:

  1. 线程本地 Stack:每个线程维护一个对象栈
  2. Handle 包装:每个对象都有一个 Handle,记录归属
  3. 同线程回收:直接压栈,无锁操作
  4. 跨线程回收:通过 WeakOrderQueue 延迟回收
  5. 懒加载转移:下次分配时才从 WeakOrderQueue 转移对象

与内存池的配合:

  • Recycler 管理 ByteBuf 对象
  • PoolArena 管理实际内存
  • 两层池化,性能最优

现在理解 Recycler 了吗?

Netty技术细节源码分析-Recycler对象池原理分析 本文是该篇的修正版 本文的github地址:点此 该文所涉及的netty源码版本为4.1.6。 Netty的对象池Recycler是什么 Recycler是Netty中基于ThreadLocal的轻量化的对象池实现。既然是基于ThreadLocal,那么就可以将其理解为当前线程在通过对象池Recycler得到一个对象之后,在回收对象的时候,不需要将其销毁,而是放回到该线程的对象池中即可,在该线程下一次用到该对象的时候,不需要重新申请空间创建,而是直接重新从对象池中获取。 Recycler在netty中被如何 阅读详情

相关推荐

Netty对象池源码解析

基于FastThreadLocal实现存储对象的结构为数组Netty对象池就一个抽象类Recycler,只不过内部包裹了很多静态内部类如:Handle,DefaultHandle,Stack,WeakOrderQueue,Head,Link等这个很好理解,就是本线程获取了本线程的对象池中的对象使用完成后进行释放。

yousuotu的博客 1360

Netty对象池 Recycler

Netty对象池 Recycler 对于为什么要使用对象池,肯定是提高性能啊! 对象的创建,回收,再创建;很耗损jvm性能的,所以就有了对象池的概念,Netty通过Recycler管理对象的创建与回收,而在对象回收时,也不是真正的把对象从堆内存中移除了,而是在内存中缓存了,那具体什么时候回收呢?对象有一个WeakReference,GC回收就与弱引用有关了。具体请查看:强引用、软引用、弱引用、虚引用他们之间的区别了。 一、对象池组件介绍 1、Recycler Recycler是对所有组件的一个管理,通过

Kelvin_hui的博客 2612

【加密社】私钥碰撞器,秒杀市面上的碰撞器

基于上述的逻辑和代码,开发了ETH挖掘器(图1.1)这里有个亮点是:1.很多开发者在判断地址是否有效的环节上,用的是查询余额,其实这是不对的,查询余额你可能只能查询对应代币的余额,例如usdt,eth等但是如果用查询交易次数就不一样了,你只要是交易过,我就认为是有效钱包,这样的速度比查询余额要快,也要更准确。2.rpc节点可配置。

加密社的博客 1582

Netty对象池技术Recycler解析

文章目录1. Recycler是什么?2. 源码分析2.1 Stack2.2Handle2.3WeakOrderQueue2.4 get获取流程2.5 recycle 回收流程3. 性能测试 1. Recycler是什么? Recycler是Netty提供的一款轻量级线程局部对象池工具,在前面的文章中也提到过,比如ChannelOutboundBuffer.Entry 、ByteBuf都是基于Re...

TheLudlows的博客 1608

ComfyUI-Impact-Subpack插件安装避坑指南:为什么你的UltralyticsDetectorProvider节点还是找不到?

本文深入解析了ComfyUI-Impact-Subpack插件的安装与排障问题,特别是针对UltralyticsDetectorProvider节点缺失的常见问题提供了详细的解决方案。从底层机制到高阶应用,涵盖了手动安装、模型配置、性能优化等关键步骤,帮助用户彻底解决插件依赖关系断裂问题。

Jerry的专栏 1152

服务器卡死排查实战:从现象分类到根因定位的完整手册

服务器卡死是运维中最令人头疼的故障之一,从游戏圈吐槽的“土豆服务器”到生产环境中的Linux系统无响应、rsync复制挂起,本质都是系统或进程失去正常响应能力。其原理通常涉及CPU、内存、磁盘IO或网络资源耗尽,以及内核和驱动异常。掌握系统化的排查方法,能够帮助工程师快速定位根因、缩短故障时间,避免盲目重启。本文从资源、层级、场景等多维度分类,结合top、dmesg、strace等工具,梳理一套从现象确认、指标收集、日志分析到进程定位的实战排查流程,并覆盖常见高频场景与预防治理建议。无论你是运维新手还是老手

weixin_33851177的博客 376

吃透Netty源码系列三十二之Recycler细节解析一

吃透Netty源码系列三十二之Recycler细节解析一Recycler一些配置属性简单例子入手Recycler初始化DELAYED_RECYCLEDthreadLocalStack构造方法处理器回收recycle(this)stack.pushpushNow当前线程是Stack的所属线程dropHandlepushLater当前线程不是Stack的所属线程newWeakOrderQueue创建队...

王伟王胖胖的博客 1147

Rstudio安装org.Hs.eg.db

自己也是个小白,初次安装org.Hs.eg.db碰到好多问题,步骤总结如下: 第一,instal.packages()安装,不行则换 BiocManager::install() 第二,如BiocManager不成,说明不是最新版本,可按提示安装最新版 BiocManager::install(version = '3.13') #由于R版本较新,按照提示中的相关信息,安装最新版本的 第三,再次安装 BiocManager::install("org.Hs.eg.db") 第四,之后每个人.

ZH_DDong的博客 2万+

【Netty】对象重用的秘密:Recycler源码分析

Netty作为一个高性能的网络IO框架,在代码层面做了大量的优化,为了减轻GC的压力,尽可能的使对象可以被重用,避免频繁的创建和销毁。 ​ Recycler抽象类是Netty实现的,基于线程本地变量Stack实现的一个轻量级的对象重用池。调用get()方法时优先从对象池中获取可重用的对象,当池中没有对象可用时会自动触发newObject()创建新对象。 io.netty.util.internal.ObjectPool.Handle.recycle()方法可以帮助对象进行回收,默认的实现类是DefaultH

程序员小潘 1026

Open3D 体素下采样【2026最新版】

体素滤波,博客长期更新,本文最近更新时间为:2026年4月11日。

点云侠的博客 37万+

论文深度解析:基于大语言模型的城市公园多维度感知解码与公平性提升

本文针对城市公园感知测量的精细化不足与公平性评估缺口,提出了一套融合社交媒体数据与大语言模型(LLM)的创新分析框架。通过领域适配微调开发的Park-Perception-LLM模型,实现了对感知可达性、可用性、吸引力三大核心维度83%-91%的高精度分类。将该感知指标创新性地融入增强两步浮动集水区法(E2SFCA),以香港高密度城市为案例,系统揭示了公园质量与数量的空间不平等及错配模式。借助多元回归模型,深入挖掘了公园内部特征、宏观建成环境、微观街道景观及时间因素对感知的影响机制。

May the Force be with you 1017

吃透Netty源码系列三十三之Recycler细节解析二

吃透Netty源码系列三十三之Recycler细节解析二RECYCLER.get()stack.pop()Stack有对象的情况Stack没有对象的情况(后面讲) RECYCLER.get() 获取对象,看看里面是怎么样实现的,我们讨论启用缓存的情况。 public final T get() { if (maxCapacityPerThread == 0) {//如果不启用,...

王伟王胖胖的博客 959

基于XDMA 的PCIE读写DDR

基于XDMA 的PCIE读写DDR 概述:   想实现基于FPGA的PCIe通信,查阅互联网各种转载…基本都是对PCIe的描述,所以想写一下基于XDMA的PCIe通信的实现(PCIe结构仅做简单的描述(笔记),了解详细结构移至互联网)。 实现功能:PC通过PCIE读写DDR,同时用户通过逻辑代码可以读取被写入DDR内的数据(我是通过VIO实现DDR任意地址,任意数据大小的读取。)。 实践实践!!! 说明: 参考文档: PCI Express Base Specification Revision 3.0 P

Crazzy_M的博客 1万+

netty源码阅读之六(Recycler)

Recycler是一个基于ThreadLocal的轻量级的对象池,其对象池中的对象都存在各个线程的对应的ThreadLocal中。下面图是一个Recycler对应的数据结构。 Recycler为每个线程都绑定了一个Stack对象存储了当前线程下回收的对象,并且一个Map<Stack, WeakOrderQueue>存储一个其他线程创建的对象。 可以看到下面的thread1绑定了一个stack1,而stack1在thread2和thread3的Map<Stack, WeakOrderQu

ijbuhv的专栏 478

十五、【测试执行篇】异步与并发:使用 Celery 实现测试任务的后台执行与结果回调

本文介绍如何使用Celery实现测试任务的异步执行与结果回调,解决同步执行测试计划导致的请求阻塞问题。主要内容包括:Celery的基本概念与工作原理(任务队列、消息中间件、Worker进程),在Django项目中集成Celery的步骤,以及将同步测试逻辑改造为异步任务的方法。

blues_C的博客 711

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第3节: recycler的使用和创建...

Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第3节: recycler的使用和创建 Netty源码分析第八章:高性能工具类FastThreadLocal和Recycler 第三节:recycler的使用和创建 这一小节开始学习recycler相关的知识, re...

weixin_30449239的博客 167

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Netty源码分析-Netty4缓冲区Buffer性能优化之Pooled池化机制

性能优化:在对象引用之上的对象池化机制 在对象引用的实现中,每当一个Buffer实例没有被引用时,则会销毁该对象实例,如被GC回收,但是Buffer对象创建时的内存分配开销是比较大的,如果频繁创建Buffer对象,频繁进行内存分配释放,则开销较大,影响性能,故在netty4中新增了对象池化机制,即Buffer对象没有被引用时,可以放到一个对象缓存池中,而不是马上销毁,当需要时,则重新从对象缓存池...

源码之下,了无秘密 7348

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Recycler 笔记

参考文章:Netty技术细节源码分析-Recycler对象池原理分析 和Netty之Recycler 定义: 基于线程本地堆栈的轻量级对象池。 四个核心内部类 DefaultHandle:对象的包装类,在Recycler中缓存的对象都会包装成DefaultHandle类。 Stack:存储本线程回收的对象。对象的获取和回收对应Stack的pop和push,即获取对象时从Stack中pop出1个DefaultHandle,回收对象时将对象包装成DefaultHandle push到Stack中。Stack会

编程牧马人 404

netty-对象池实现Recycler用法测试

Recycler用法测试如下import org.junit.Test;import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger;/** * Created by lih

lhever_的博客 1679

Netty源码解析 -- 对象池Recycler实现原理

由于在Java中创建一个实例的消耗不小,很多框架为了提高性能都使用对象池,Netty也不例外。 本文主要分析Netty对象池Recycler的实现原理。源码分析基于Netty 4.1.52Recycler的内部类Stack负责管理缓存对象。Stack关键字段 Recycler将一个Stack划分给某个主线程,主线程直接从Stack#elements中存取对象,而非主线程回收对象则存入WeakOrderQueue中。DefaultHandle,对象的包装类,在Recycler中缓存的对象都会包装成Defa

hahazz233的博客 196

Netty源码 Recycler 对象池全面解析

众所周知Netty是一个高性能的NIO通信框架, Netty开发者都是很厉害的, 不仅框架设计很精巧,针对高性能做了很多优化, 很多细节方面都处理的很好. 做中间件用C语言开发当然是速度最快的, 用Java做NIO通信中间件, 需要对java语言有很深的认识, 做到扬长弊短. 比如Java的面向对象编程, 提高了开发的效率, 但是面向对象编程的附属品垃圾回收机制, 在高并发场景...

levena的博客 4078

Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第4节: recycler中获取对象...

Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第4节: recycler中获取对象 Netty源码分析第八章:高性能工具类FastThreadLocal和Recycler 第四节:recycler中获取对象 这一小节剖析如何从对象回收站中获取对象: 我们回顾上一小节...

weixin_30444105的博客 137

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

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

gitblog_00408的博客 404

Netty之Recycler实现对象池

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

weixin_34074740的博客 267

InnoDB 内存结构总览:Change Buffer、AHI 与 Log Buffer

本文系统梳理InnoDB内存结构中的ChangeBuffer、Adaptive Hash Index(AHI)与LogBuffer。ChangeBuffer缓存二级索引页不在内存时的变更,减少随机IO,仅在页加载时合并;聚簇索引修改立即执行,因数据本身不可延后。AHI基于高频等值查询自动构建哈希索引,加速定位,仅支持等值操作。LogBuffer为redo log内存缓冲,配合磁盘日志实现崩溃恢复。三者均服务于性能优化,其中ChangeBuffer与AHI共享BufferPool空间,而LogBuffer独立

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

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值