zoukankan      html  css  js  c++  java
  • Netty源码分析第8章(高性能工具类FastThreadLocal和Recycler)---->第5节: 同线程回收对象

     

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

     

    第五节: 同线程回收对象

     

    上一小节剖析了从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);
    }

    这里就是一个同线程回收对象的典型场景, 在一个线程中将对象创建并且回收, 我们的User对象定义了recycle方法

    static class User{
        private final Recycler.Handle<User> handle;
        public User(Recycler.Handle<User> handle){
            this.handle=handle;
        }
        public void recycle(){
            handle.recycle(this);
        }
    }

    这里的recycle是通过handle对象的recycle方法实现对象回收的, 这里实际调用的是DefaultHandle的recycle方法

    我们跟进recycle方法:

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

    这里如果回收的对象为null, 则抛出异常

    如果不为null, 则通过自身绑定stack的push方法将自身push到stack中

    跟到push方法中:

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

    这里首先判断当前线程, 和创建stack的时候保存的线程是否是同一线程, 如果是, 说明是同线程回收对象, 则执行pushNow方法将对象放入stack中

    跟到pushNow方法中:

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

    如果第一次回收, item.recycleId和item.lastRecycledId都为0, 所以不会进入if块, 我们继续往下看

     item.recycleId = item.lastRecycledId = OWN_THREAD_ID 这一步将handle的recycleId和lastRecycledId赋值为OWN_THREAD_ID, OWN_THREAD_ID在每一个recycle中是唯一固定的, 这里我们只需要记得这个概念就行

    然后获取当前size

    如果size超过上限大小, 则直接返回

    这里还有个判断dropHandle, 我们跟进去:

    boolean dropHandle(DefaultHandle<?> handle) {
        if (!handle.hasBeenRecycled) {
            if ((++handleRecycleCount & ratioMask) != 0) {
                return true;
            }
            handle.hasBeenRecycled = true;
        }
        return false;
    }

     if (!handle.hasBeenRecycled) 表示当前对象之前是否没有被回收过, 如果是第一次回收, 这里会返回true, 然后进入放到if

    再看if中的判断 if ((++handleRecycleCount & ratioMask) != 0) 

    handleRecycleCount表示当前位置stack回收了多少次对象(回收了多少次, 不代表回收了多少个对象, 因为不是每次回收都会被成功的保存在stack), ratioMask我们之前分析过是7, 这里 (++handleRecycleCount & ratioMask) != 0 表示回收的对象数如果不是8的倍数, 则返回true, 表示只回收1/8的对象

    然后将hasBeenRecycled设置为true, 表示已经被回收

    回到pushNow方法中:

    如果size的大小等于stack中的数组elements的大小, 则将数组elements进行扩容

    最后将size通过数组下标的方式将当前handle设置到elements的元素中, 并将size进行自增

    以上就是同线程回收对象的逻辑

     

    上一节: reclycer中获取对象

    下一节: 异线程回收对象

     

  • 相关阅读:
    【分治法】线性时间选择(转)
    【分治法】最接近点对问题(转)
    概率DP入门总结 16题(转)
    动态规划初探及什么是无后效性? (转)
    第15章DP(转)
    整数快速乘法/快速幂+矩阵快速幂+Strassen算法 (转)
    矩阵乘法的理解(转)
    算法导论第4章习题与思考题(转)
    Transaction Script模式
    注册服务
  • 原文地址:https://www.cnblogs.com/xiangnan6122/p/10209008.html
Copyright © 2011-2022 走看看