Java环形缓冲区类

import java.util.LinkedHashMap;

/**
 * @Description: circularBuffer util
 * @author Administrator
 * @date 2017-5-1
 */
public class CircularBuffer<T> {
	private Object[] buffer = null; // 数据容器
	private int capacity = 0; // 缓冲区长度
	private int indexForPut = 0; // put索引 (下一个要写入的位置)
	private int indexForGet = 0; // get索引 (下一个要读取的位置)

	/**
	 * 线程的几种状态
	 */
	enum ThreadState {
		BLOCK, /* 暂时阻塞 */
		RUNNING, /* 运行 */
		OVER, /* 线程顺利完成 */
		INTERRUPT /* 中断,(暂时用不到) */
	}

	/* put 和 get 的线程状态标记 */
	private ThreadState putThreadState = ThreadState.RUNNING;
	private ThreadState getThreadState = ThreadState.RUNNING;
	LinkedHashMap<Integer, String> msgs = new LinkedHashMap<Integer, String>();

	/**
	 * 指定长度的缓冲区
	 * 
	 * @param capacity
	 */
	public CircularBuffer(int capacity) {
		this.capacity = capacity;
		this.buffer = new String[this.capacity];
	}

	/**
	 * 写入数据,注意此函数会导致阻塞
	 * 
	 * @param element
	 */
	public void putElement(T element) {
		// 有空位就插入~
		// 没空位就轮询,直到有空位可插入为止~
		while (null != this.buffer[this.indexForPut]) {
			try {
				this.setPutThreadState(ThreadState.BLOCK); // put线程标记为:阻塞
				Thread.sleep(100);

			} catch (InterruptedException e) {
				e.printStackTrace(); // 例行公事
				System.out.println("线程意外停止,正在检查");

			}
		}
		this.setPutThreadState(ThreadState.RUNNING); // put线程标记为:正在运行

		// 填入元素,将put索引指向下一元素位~
		this.buffer[this.indexForPut] = element;
		this.indexForPut++;
		this.indexForPut %= this.capacity;
	}

	/**
	 * 取数据,注意此函数会阻塞,若put线程结束且缓冲区为空时函数会返回null
	 * 
	 * @return 下一个T元素 或者 null
	 */
	@SuppressWarnings("unchecked")
	public T getElement() {
		// 有元素就拿出~
		// 没元素就轮询,直到有元素可拿为止~ 若是put完毕、 数据取空,则返回null以告知调用者
		while (null == this.buffer[this.indexForGet]) {
			try {
				this.setGetThreadState(ThreadState.BLOCK); // get线程标记为:阻塞
				if (this.isPutedOver() && this.isEmputy()) {
					this.setGetThreadState(ThreadState.OVER);
					return null;
				}
				Thread.sleep(100);

			} catch (InterruptedException e) {
				e.printStackTrace();
				System.out.println("线程意外停止");

			}
		}
		this.setGetThreadState(ThreadState.RUNNING); // get线程标记为:正在运行

		/* 拿到元素,buffer腾出该元素位,将get索引指向下一元素~ */
		Object temp = this.buffer[this.indexForGet];
		this.buffer[this.indexForGet] = null;
		this.indexForGet++;
		this.indexForGet %= this.capacity;

		return (T) temp; // 返回拿到的元素引用
	}

	/**
	 * 检查此环形缓冲区是否为空
	 * 
	 * @return boolean true则表示为空,false则不为空
	 */
	public boolean isEmputy() {
		// 新元素是以 索引0 向 索引length 的顺序 put入
		// 有鉴于此,这里倒过来枚举,防止出现“同向追赶”导致落空的的囧事;
		for (int i = this.buffer.length - 1; i > 0; i--) {
			if (this.buffer[i] != null) {
				return false;
			}
		}
		return true;
	}

	/**
	 * 检查 put 线程和 get 线程是否同时阻塞,
	 * 
	 * @return boolean true-挂球 false-良好
	 */
	public boolean isAllBlock() {
		return (this.getThreadState == ThreadState.BLOCK && this.putThreadState == ThreadState.BLOCK);
	}

	/**
	 * 检查数据源是否缓冲完毕
	 * 
	 * @return boolean true-完成 false-未完成
	 */
	public boolean isPutedOver() {
		return this.putThreadState == ThreadState.OVER;
	}

	public void setPutThreadState(ThreadState putThreadState) {
		this.putThreadState = putThreadState;
	}

	private void setGetThreadState(ThreadState getThreadState) {
		this.getThreadState = getThreadState;
	}

}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值