环形队列(缓冲队列)

         之前了解到Hadoop的shuffle过程中,能边读边写,其实是底层实现了一个环形队列的缓冲区,这样能大大的提高性能。于是对环形队列产生了好感,进而研究一番。

          在此,做个Demo来测试下环形队列。主要的思路就是定义一个固定长度的数组 + 入队与出队两个游标  来实现环形队列!

代码如下:

package algorithm;

/**
 * @Description: 环形队列,对于那种固定大小的缓存区,绝佳使用场景
 * @Author yunyao.huang
 * @Date 2018年8月22日
 */
public class RingQueue {

	// 队列原型数组 , 注意:集合不适合,因为一旦填充满了会自动扩容
	private Object[] queue;

	// 入队与出队游标 ,相似于指针的运用 ,用来标记入队与出队的元素
	private int inIndex, outIndex = 0;

	// 缓存区的大小
	private static final int Size = 5;

	public RingQueue() {
		queue = new Object[Size];
	}
    
    // 返回数据的长度
	public int getLength() {
		int length = (inIndex - outIndex + Size) % Size;
		return length;

	}

	// 入队
	public boolean joinQueue(Object obj) {
		if (inIndex % Size == outIndex && queue[inIndex] != null) { // 判断队列是否已满
			System.out.println("=======>   入队失败!队列已满!");
			return false;
		}
		// 不满的情况 设置当前队列入队节点为传入对象
		queue[inIndex] = obj;
		inIndex = (inIndex + 1) % Size; // 更新入队游标(核心代码)
		return true;
	}

	// 出队
	public Object quitQueue() {
		if (inIndex == outIndex && queue[inIndex] == null) { // 判断队列是否为空
			System.out.println("=======>   出队失败!队列已空!");
			return null;
		}
		// 不空的情况 获取当前出队节点的对象
		Object result = queue[outIndex];
		queue[outIndex] = null;
		outIndex = (outIndex + 1) % Size; // 更新出队游标(核心代码)
		return result;
	}

	// 测试
	public static void main(String args[]) {
		RingQueue queue = new RingQueue();
		queue.joinQueue(1);
		queue.joinQueue(2);
		queue.joinQueue(3);
		queue.joinQueue(4);
		queue.joinQueue(5);
		queue.joinQueue(6);
		int length0 = queue.getLength();
		System.out.println("数据长度为==> "+length0 + "\t" + "出队对象为==> " + queue.quitQueue());
		int length = queue.getLength();
		System.out.println("数据长度为==> "+length + "\t" + "出队对象为==> " + queue.quitQueue());
		int length2 = queue.getLength();
		System.out.println("数据长度为==> "+length2 + "\t" + "出队对象为==> " + queue.quitQueue());
		int length3 = queue.getLength();
		System.out.println("数据长度为==> "+length3 + "\t" + "出队对象为==> " + queue.quitQueue());
		int length4 = queue.getLength();
		System.out.println("数据长度为==> "+length4 + "\t" + "出队对象为==> " + queue.quitQueue());
		int length5 = queue.getLength();
		System.out.println("数据长度为==> "+length5 + "\t" + "出队对象为==> " + queue.quitQueue());
		queue.joinQueue(1);
		queue.joinQueue(2);
		queue.joinQueue(3);
		System.out.println(queue.quitQueue());
		System.out.println(queue.quitQueue());
		System.out.println(queue.quitQueue());
	}
}

 测试效果如下:

      由于缓存区大小为5,当添加第六个数据时,显示队列已满,于是就出队,当出队到队列为空时,显示队列为空。

      另外如果遇到性能瓶颈,可以考虑让入队和出队的游标使用&运算,因为位运算是速度最快的,计算机是用二进制来储存任何数据的。这里不再细说。

猜你喜欢

转载自blog.csdn.net/weixin_42245930/article/details/81943507