zoukankan      html  css  js  c++  java
  • Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第4节: recycler中获取对象


    Netty源码分析第八章: 高性能工具类FastThreadLocal和Recycler

     

    第四节: recycler中获取对象

     

    这一小节剖析如何从对象回收站中获取对象:

    我们回顾上一小节demo的main方法中, 从回收站获取对象

    public static void main(String[] args){
        User user1 = RECYCLER.get();
        user1.recycle();
        User user2 = RECYCLER.get();
        user2.recycle();
        System.out.println(user1==user2);
    }

    这个通过Recycler的get方法获取对象, 我们跟到get方法中:

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

    首先判断maxCapacityPerThread是否为0, maxCapacityPerThread代表stack最多能缓存多少个对象, 如果缓存0个, 说明对象将一个都不会回收

    这个通过调用newObject创建一个对象, 并传入一个NOOP_HANDLE, NOOP_HANDLE是一个handle, 我们看其定义:

    private static final Handle NOOP_HANDLE = new Handle() {
        @Override
        public void recycle(Object object) {
            
        }
    };

    这里的recycle方法是一个空实现, 代表不进行任何对象回收

    回到get方法中:

    我们看第二步 Stack<T> stack = threadLocal.get(); 

    这里通过FastThreadLocal对象拿到当前线程的stack, 有关FastThreadLocal获取对象的逻辑之前小节剖析过, 这里不再赘述

    获取stack之后, 从stack中pop出一个handle, 这个handle做用我们稍后分析

    如果取出的对象为null, 说明当前回收站内没有任何对象, 通常第一次执行到这里对象还没回收, 这里就会是null, 这样则会通过stack.newHandle()创建一个handle

    创建出来的handle的value属性, 通过我们重写的newObject方法进行赋值, 也就是我们demo中的user

    我们跟进newHandle方法:

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

    这里创建一个DefaultHandle对象, 并传入this, 这里的this是当前stack

    跟到DefaultHandle的构造方法中:

    DefaultHandle(Stack<?> stack) {
        this.stack = stack;
    }

    这里初始化了stack属性

    DefaultHandle中还有个value的成员变量

    private Object value;

    这里的value就用来绑定回收的对象本身

    回到get方法中:

    分析handle, 我们回到上一步:

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

    我们分析从stack中弹出一个handle的逻辑

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

    首先拿到size, size表示当前stack的对象数

    如果size为0, 则调用scavenge方法, 这个方法是异线程回收对象的方法, 我们放在之后的小节进行分析

    size大于零, 则size进行自减, 代表取出一个元素

    然后通过size的数组下标的方式将handle取出

    之后将当前下标设置为null

    最后将属性recycleId, lastRecycledId, size进行赋值

    recycleId和lastRecycledId我们会在之后的小节进行分析

    回到get方法中:

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

    无论是从stack中弹出的handle, 还是创建的handle, 最后都要通过handle.value拿到我们实际使用的对象

    以上就是从对象回收站获取对象的过程

     

    上一节: recycler的使用和创建

    下一节: 同线程回收对象

     

  • 相关阅读:
    【测试管理】如何简单的新增用例模块
    【自动化框架开发】node.js+selenium基于mac框架架设v1.0.1
    【自动化框架开发】node.js+selenium基于mac框架架设v1.0.0
    python--导入导出数据
    python爬虫--运用cookie模拟登录知乎
    python爬虫--连接数据库2
    python爬虫--模拟登录知乎
    python爬虫--连接数据库1
    python爬虫--储存本地
    python爬虫--解析网页几种方法之BeautifulSoup
  • 原文地址:https://www.cnblogs.com/xiangnan6122/p/10208952.html
Copyright © 2011-2022 走看看