之前了解到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,当添加第六个数据时,显示队列已满,于是就出队,当出队到队列为空时,显示队列为空。
另外如果遇到性能瓶颈,可以考虑让入队和出队的游标使用&运算,因为位运算是速度最快的,计算机是用二进制来储存任何数据的。这里不再细说。