美文网首页
记录一个数据结构

记录一个数据结构

作者: 跳跃在代码上的豆豆 | 来源:发表于2021-04-20 20:39 被阅读0次
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

import hooyee.IDataElement;

/**
 * 一个缓存队列,用于管理
 * [a[], b[], c[]]形式的数据,从其中取出指定长度的数据,若指定的长度小于队首的可用长度,则返回该队首元素(该元素不出队),并修改该元素的region.
 * 若大于队首,则直接返回队首,并将队首元素出队,可用范围是 T 的[startPosition, endPosition)
 * @param <T>
 */
public class DataCache<T extends IDataElement> {
    private long MAX_SIZE;
    private final AtomicLong totalSize = new AtomicLong();
    /**
     * dataQueue的poll和offer操作也需要保证线程安全,因此变更数据结构
     */
    Queue<T> dataQueue = new ConcurrentLinkedQueue<>();

    /**
     * offer和poll需要通过overflow来确认,而overflow又依赖于updateSize,因此需要保证poll和offer的整个流程的原子性(其实只要保证offer,因为poll是会减小他的值,这样只会更加满足条件)
     **/
    private final ReentrantLock pollLock = new ReentrantLock();
    private final ReentrantLock offerLock = new ReentrantLock();

    public DataCache() {
        MAX_SIZE = 1024 * 1024 * 4;
    }

    public DataCache(long maxSize) {
        MAX_SIZE = maxSize;
    }

    /**
     * 线程安全的, 只用于T为 IElement的时候,若不是与不带参的效果一样
     * @param length 从队列的第一个元素中获取指定长度的数据,如果第一个元素小于改长度,调用poll,若大于则调用peek,并移动offset等信息
     * @return
     */
    public @Nullable T poll(int length) {
        pollLock.lock();
        try {
            T data = dataQueue.peek();
            if (data != null) {
                removeIfOver(data, length);
            }
            return data;
        } finally {
            pollLock.unlock();
        }
    }

    /**
     * 若是queue中的元素可用长度[endPosition, length)超过入参length,则不出队列,以备下次使用
     * @param data
     * @param length
     */
    private boolean removeIfOver(@NonNull T data, int length) {
        // 未被读取的数据
        if (data.getLength() - data.getEndPosition() > length) {
            // 大于length只截取[start, end)部分
            // 移动被读取的region[start, end)
            data.setStartPosition(data.getEndPosition());
            data.setEndPosition(data.getEndPosition() + length);
            return false;
        } else {
            data.setStartPosition(data.getEndPosition());
            data.setEndPosition(data.getLength());
            dataQueue.poll();
            updateSize(-data.getLength());
            return true;
        }
    }

    /**
     * 线程安全的
     *
     * @param data
     */
    public void offer(@NonNull T data) {
        if (overflow()) {
            return;
        }
        offerLock.lock();
        try {
            if (!overflow()) {
                dataQueue.offer(data);
                updateSize(data.getLength());
            } else {

            }
        } finally {
            offerLock.unlock();
        }
    }

    /**
     * 清空数据
     */
    public void clear() {
        dataQueue.clear();
        totalSize.set(0);
    }

    private void updateSize(long size) {
        totalSize.addAndGet(size);
    }

    /**
     * true : 满了
     *
     * @return
     */
    private boolean overflow() {
        return totalSize.get() >= MAX_SIZE;
    }
}

相关文章

  • 线性表 - Sequential List

    0 序言1 简析线性表2 记录线性表的使用 序言 基本数据结构记录系列,记录基本的数据结构实现和JDK、SDK等中...

  • 重构(五)重构名录-封装

    封装记录Encapsulate Record � 当复杂的数据结构记录需要频繁变化时,那么将其组织成一个类,对外提...

  • 重构(五)重构名录-封装

    封装记录Encapsulate Record 当复杂的数据结构记录需要频繁变化时,那么将其组织成一个类,对外提供变...

  • sql学习之mysql索引

    一、索引是什么 索引就是一个数据结构,我们把表中的记录用一个适合高效查找的数据结构来表示,目的就是让查询变得更高效...

  • 时间复杂度

    近日在研究算法数据结构相关的知识,学习到一个名词,时间复杂度,特来此记录下。 时间复杂度:先来看看《“大话数据结构...

  • Redis简单数据结构及适用场景记录

    Redis简单数据结构及适用场景记录 1、五种基础数据结构Redis 所有的数据结构都是以唯一的 key 字符串作...

  • 记录一个数据结构

  • Draft.js的数据结构

    Draft.js的数据结构 Draft.js使用EditorState来保存数据结构顶层,其中记录了用于展示数据的...

  • Java 数据结构 循序表

    @[TOC](Java 数据结构-循序表) 数据结构 复习记录 初次编写博客,希望以后也能养成这种习惯,话不多说,...

  • 2019-04-30

    数据结构记录笔记 第一章:数据结构概论 1.1数据结构的概念 数据是信息的载体,是描述客观事物的数、字符,以及所有...

网友评论

      本文标题:记录一个数据结构

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