Java码界探秘 Java码界探秘
首页
  • 基础

    • 对象的概念
    • 万物皆对象
    • 控制流
    • 初始化和垃圾回收
    • 封装
    • 复用
    • 多态
    • 接口
    • 内部类
    • 集合
  • 高级

    • 函数式编程
    • 流式编程
    • 异常
    • 代码校验
    • 文件
    • 字符串
    • 类型信息
    • 泛型
    • 数组
    • 枚举
    • 注解
    • 并发编程
    • 设计模式
  • 扩展

    • 编程指南
    • 文档注释
    • 对象传递和返回
    • 流式 IO
    • New IO
    • 理解 equals 和 hashCode 方法
    • 关于集合
    • 并发底层原理
    • 数据压缩
    • 对象序列号
    • C++ 和 Java 的优良传统
  • 基础

    • Netty源码解析
    • Netty概述
    • Netty中的buffer
    • Channel中的Pipeline
    • Netty与Reactor模式
    • Netty中的Handler
    • Netty中的HashedWheelTimer
    • Netty中的Channel(下)
    • Netty中的异步
  • 高级

    • Recycler对象池分析
    • FastThreadLocal源码解析
    • SocketChannel 读取ByteBuf 的过程
    • Netty 内存池分析
    • Netty如何实现高性能内存管理
    • 线程池EventLoopGroup源码分析
    • Netty实例构建一个socks proxy
    • Netty4.x用户指南
    • Netty4和Netty3对比
    • Netty3.2用户指南
    • 3.2 ChannelEvent (opens new window)
    • Netty3.x源码解析
    • 4.x DefaultPromise (opens new window)
  • 基础教程

    • Hello, World!
    • 变量Variables
    • 将参数传递给脚本
    • 数组
    • 数组比较
    • 基础运算符
    • 基础字符串操作
    • 逻辑表达式
    • 循环
    • Shell函数
  • 高级教程

    • 特殊变量
    • 字符串操作
    • 捕捉信号命令
    • 文件测试
    • 管道
    • 输入输出
    • Sed命令介绍
    • Sftp命令介绍
  • 知行:技术人的管理之路(脑图)
  • 软件开发中团队首领的好坏之分
  • 制定规划的策略
  • 打造最佳开发团队的几点建议
  • 给老板汇报技术规划的一些要点
  • 技术的价值怎么在非技术领导心里提现出来?
  • 性格内向,不善言辞的人能做管理吗?
  • 研发管理:与员工一对一交流的执行与反思
首页
  • 基础

    • 对象的概念
    • 万物皆对象
    • 控制流
    • 初始化和垃圾回收
    • 封装
    • 复用
    • 多态
    • 接口
    • 内部类
    • 集合
  • 高级

    • 函数式编程
    • 流式编程
    • 异常
    • 代码校验
    • 文件
    • 字符串
    • 类型信息
    • 泛型
    • 数组
    • 枚举
    • 注解
    • 并发编程
    • 设计模式
  • 扩展

    • 编程指南
    • 文档注释
    • 对象传递和返回
    • 流式 IO
    • New IO
    • 理解 equals 和 hashCode 方法
    • 关于集合
    • 并发底层原理
    • 数据压缩
    • 对象序列号
    • C++ 和 Java 的优良传统
  • 基础

    • Netty源码解析
    • Netty概述
    • Netty中的buffer
    • Channel中的Pipeline
    • Netty与Reactor模式
    • Netty中的Handler
    • Netty中的HashedWheelTimer
    • Netty中的Channel(下)
    • Netty中的异步
  • 高级

    • Recycler对象池分析
    • FastThreadLocal源码解析
    • SocketChannel 读取ByteBuf 的过程
    • Netty 内存池分析
    • Netty如何实现高性能内存管理
    • 线程池EventLoopGroup源码分析
    • Netty实例构建一个socks proxy
    • Netty4.x用户指南
    • Netty4和Netty3对比
    • Netty3.2用户指南
    • 3.2 ChannelEvent (opens new window)
    • Netty3.x源码解析
    • 4.x DefaultPromise (opens new window)
  • 基础教程

    • Hello, World!
    • 变量Variables
    • 将参数传递给脚本
    • 数组
    • 数组比较
    • 基础运算符
    • 基础字符串操作
    • 逻辑表达式
    • 循环
    • Shell函数
  • 高级教程

    • 特殊变量
    • 字符串操作
    • 捕捉信号命令
    • 文件测试
    • 管道
    • 输入输出
    • Sed命令介绍
    • Sftp命令介绍
  • 知行:技术人的管理之路(脑图)
  • 软件开发中团队首领的好坏之分
  • 制定规划的策略
  • 打造最佳开发团队的几点建议
  • 给老板汇报技术规划的一些要点
  • 技术的价值怎么在非技术领导心里提现出来?
  • 性格内向,不善言辞的人能做管理吗?
  • 研发管理:与员工一对一交流的执行与反思
  • 基础

    • Netty源码解析
    • Netty概述
    • Netty中的buffer
    • Channel中的Pipeline
    • Netty与Reactor模式
    • Netty中的Handler
    • Netty中的HashedWheelTimer
    • Netty中的Channel(下)
    • Netty中的异步
  • 高级

    • Recycler对象池分析
      • (1) Recycler类结构
        • 1\. Handler组件
        • 2\. Stack组件
        • 3\. WeakOrderQueue组件
      • 总结
    • FastThreadLocal源码解析
    • SocketChannel 读取ByteBuf 的过程
    • Netty 内存池分析
    • Netty如何实现高性能内存管理
    • 线程池EventLoopGroup源码分析
    • Netty实例构建一个socks proxy
    • Netty4.x用户指南
    • Netty4和Netty3对比
    • Netty3.2用户指南
    • Netty3.x源码解析
  • Netty
  • 高级
daichangya
2024-05-10
目录

Recycler对象池分析

# (1) Recycler类结构

  • Recycler是一个抽象类,在目标类中创建Recycler对象池实例时需要实现newObject(Handler handler)方法用来创建特定类的实例;

  • Recycler对象池内部是用一个对象数组维护对象池中的对象实例,对外提供统一的对象创建和回收接口:

    • Recycler#get方法 : 是获取对象池中对象的入口, 如果有可用对象,直接返回, 没有就调用newObject()方法创建一个.

    • Recycler#recycle方法: 是对象使用完毕后回收对象,只能回收当前线程创建的对象 现在已经标记@Deprecated不建议使用了, 建议使用Recycler.Handle#recycler方法,可以回收不是当前线程创建的对象, 复用性和性能更好了.

  • Recycler对象池的实现主要是通过三个核心组件:Handler,WeakOrderQueue和Stack

# 1. Handler组件

  • Handler组件主要用来对外提供一个recycle()对象回收接口

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.push(this);
    }
}
  • 每个池化对象在newObject()创建时都会绑定一个Handler用作该对象的回收;

protected WrapRecycler newObject(Handle<WrapRecycler> handle) {
    return new WrapRecycler(handle);
}    
  • 每个Handle关联一个value字段,用于存放具体的池化对象,在对象池中,所有的池化对象都被这个Handle包装,Handle是对象池管理的基本单位,Stack中存储管理的也是Handler类;

    • 调用get()方法从对象池中获取复用对象,如果对象池为空则在stack中创建新的Handler实例,并通过newObject()方法创建对象赋给handler.value属性;

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;
}

# 2. Stack组件

  • 通过FastThreadLocal类每个线程维护着一个与线程绑定的stack,用来存储复用的对象

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);
    }
};
  • 线程在通过Recycler的get()方法获取复用对象时,首先获取与当前线程绑定的stack,再从Stack中pop出Handler包装实例

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. WeakOrderQueue组件

  • WeakOrderQueue是Recycler的一个内部私有类,用来暂存待回收的对象;Handler.recycler()可以回收不是当前线程创建的对象主要依靠WeakOrderQueue实现;

private static final FastThreadLocal<Map<Stack<?>, WeakOrderQueue>> DELAYED_RECYCLED =
        new FastThreadLocal<Map<Stack<?>, WeakOrderQueue>>() {
    @Override
    protected Map<Stack<?>, WeakOrderQueue> initialValue() {
        return new WeakHashMap<Stack<?>, WeakOrderQueue>();
    }
};
  • 如果是当前线程创建的对象, 直接就把对象放到当前线程对应的Stack中. 如果不是, 则放入WeakOrderQueue中;每个线程维护着一个WeakHashmap

public void recycle(Object object) {
    if (object != value) {
        throw new IllegalArgumentException("object does not belong to handle");
    }
    stack.push(this);
}

void push(DefaultHandle<?> item) {
    Thread currentThread = Thread.currentThread();
    if (thread == currentThread) {
        pushNow(item);
    } else {
        pushLater(item, currentThread);
    }
}

private void pushLater(DefaultHandle<?> item, Thread thread) {
    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;
        }

        if ((queue = WeakOrderQueue.allocate(this, thread)) == null) {
            return;
        }
        delayedRecycled.put(this, queue);
    } else if (queue == WeakOrderQueue.DUMMY) {
        return;
    }

    queue.add(item);
}
  • 在从Stack获取对象池时,如果Stack中可用对象为空,会尝试遍历多线程对应的WeakOrderQueue链表中回收恢复对象;

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;
}

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;
}

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 {
        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.setNext(next);
            }
        } else {
            prev = cursor;
        }

        cursor = next;

    } while (cursor != null && !success);

    this.prev = prev;
    this.cursor = cursor;
    return success;
}

这里写图片描述


public class RecyclerTest {
    static class WrapRecycler{

        private boolean tmp ;
        private final static Recycler<WrapRecycler> RECYCLER = new Recycler<WrapRecycler>() {
            @Override
            protected WrapRecycler newObject(Handle<WrapRecycler> handle) {
                return new WrapRecycler(handle);
            }
        };

        Recycler.Handle<WrapRecycler> handle;
        WrapRecycler(Recycler.Handle<WrapRecycler> handle){
            this.handle = handle;
            this.tmp = false;
        }

        static WrapRecycler getInstance(){
            return RECYCLER.get();
        }

        void recycle(){
            this.tmp = false;
            handle.recycle(this);
        }

        public boolean getTmp(){
            return tmp;
        }

        public void setTmp(boolean tmp){
            this.tmp = tmp;
        }
    }


    public static void main(String[] args) {
        WrapRecycler instance = WrapRecycler.getInstance();
        System.out.println(instance.hashCode());
        System.out.println(instance.getTmp());
        instance.setTmp(true);
        System.out.println(instance.getTmp());
        instance.recycle();
        instance = WrapRecycler.getInstance();
        System.out.println(instance.hashCode());
        System.out.println(instance.getTmp());
    }
}
  • 运行结果,两次获取的对象的hashcode哈希值相同说明是同一个对象

41359092

false

true

41359092

false

# 总结

  • Netty实现的轻量级的对象池实现了对象的复用和回收,核心组件包括Stack,WeakOrderQueue和Handler

  • Stack相当于MyBatis的一级缓存,与线程绑定,线程内对象的获取和回收都使用绑定的Stack;复用对象时直接从Stack中申请,使用完后如果对象是自己创建的则放入Stack;

  • 在对象回收时候如果对象不是当前线程创建的则不能放入Stack中回收,而是放入WeakOrderQueue中,所有的Queue组成一个链表作为对象回收的仓库,当Stack中无可用的对象时会遍历链表回收对象,实现了多线程之间对象回收的共享;

这里写图片描述

上次更新: 2024/05/11, 17:55:08
Netty中的异步
FastThreadLocal源码解析

← Netty中的异步 FastThreadLocal源码解析→

Theme by Vdoing | Copyright © 2019-2024 daichangya | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式