美文网首页
Okio之SegmentPool

Okio之SegmentPool

作者: OkCoco | 来源:发表于2017-12-03 12:26 被阅读0次

    同样,先看类简介:

    A collection of unused segments, necessary to avoid GC churn and zero-fill.
    This pool is a thread-safe static singleton.
    

    大概是:没被使用的Segment的一个收集器。必要滴避免了GC导致的内存抖动和零填充。这个SegmentPool是一个线程安全的静态单例。

    常量

      /** SegmentPool所能容你的最大字节数 */
      // TODO: Is 64 KiB a good maximum size? Do we ever have that many idle segments?
      //注:64KB是不是一个比较好的内存限制呢?我也不知道。但是它相当于8个Segment的大小,一般来说是足够了。
      static final long MAX_SIZE = 64 * 1024; // 64 KiB.
    
      /** Singly-linked list of segments. */
      static Segment next;
    
      /** 当前池里(pool)所有的字节数 */
      static long byteCount;
    
    

    从这些变量可以大概得出:SegmentPool大概就是一个单链表或队列等线性结构,也就是一个大概8个Segment组成的线性结构,节点就是Segment。

    方法

    • recycle(Segment):void 回收Segment,以待复用
    static void recycle(Segment segment) {
        //将要回收的Segment还在使用中,不能进行回收,报异常!
        if (segment.next != null || segment.prev != null) throw new IllegalArgumentException();
        // 这是个处于共享状态的Segment,不能进行回收
        if (segment.shared) return; 
        //加锁处理回收操作,避免多线程环境的干扰
        synchronized (SegmentPool.class) {
          //若是当前池内的字节数byteCount加上一个Segment的最大容量已经超出了pool的最大容量,
          //表示pool空间不足,那就不能就行回收
          if (byteCount + Segment.SIZE > MAX_SIZE) return; 
          //改变当前池内字节量
          byteCount += Segment.SIZE;
          //添加到头部,所以应该是单链表结构
          segment.next = next;
          //重置Segment的pos和limit变量值
          segment.pos = segment.limit = 0;
          next = segment;
        }
      }
    

    重置过程如下:
    1、调用之前的关系

    image.png
    2、segment.next = next
    image.png
    3、next = segment;
    image.png
    此时,我更愿意把SegmentPool的实例对象当做整个链表的Head,相当于头指针,仅仅有一个方便插入Segment的作用。

    • take():Segment 获取Segment进行复用
    static Segment take() {
        //加锁,同一时间内只能有一个对象发访问这段代码块
        synchronized (SegmentPool.class) {
          if (next != null) {
            Segment result = next;
            next = result.next;
            result.next = null;
            byteCount -= Segment.SIZE;
            return result;
          }
        }
        return new Segment(); 
      }
    

    得到一个可以重用的Segment,若池内不存在可以复用的Segment,则直接new出来使用。若不为空,则取出聊飙升第一个Segment即可,当然,还得做断链、重新连接保持链式操作、重新计算池内容量大小等操作。



    与Segment的数据结构不同,pool只是用了单链表结构。因为对于复用的segment来说,只要能在池内找到,定然可以复用,故而不需要额外的操作,使用单链表已经是很简单明了的了。至此,SegmentPool的分析大概结束。

    相关文章

      网友评论

          本文标题:Okio之SegmentPool

          本文链接:https://www.haomeiwen.com/subject/okjabxtx.html