队列介绍
队列是一种线性表,它支持 先进先出(FIFO),
尾部添加、头部删除,跟我们生活中的排队类似。
队列类型
单队列
单队列就是常见的队列, 每次添加元素时,都是添加到队尾:
单队列会出现“假溢出”现象,每次从队首删除元素,元素都要上前移动一个位置,能放的空位就相对减少了。
循环队列
我们可以将队列看成一个首位相连的环。当一个元素从队列删除后,新空余出来的空间可以作为队列的尾部。
插入的时候,根据实际数据量count与数组长度比较,未满根据数组新增标志putIndex插入数据,如果数组下标临界,设为0重新开始,count++;
删除的时候,判断有无实际数据count,有的话根据取数据删除标志takeIndex,若takeIndex走到最后,从0开始,count–;
阻塞队列和并发队列
阻塞队列其实就是在队列基础上增加了阻塞操作。简单来说,就是在队列为空的时候,从队头取数据会被阻塞。因为此时还没有数据可取,直到队列中有了数据才能返回;如果队列已经满了,那么插入数据的操作就会被阻塞,直到队列中有空闲位置后再插入数据,然后再返回。
线程安全的队列我们叫作并发队列。最简单直接的实现方式是直接在 enqueue()、dequeue() 方法上加锁,但是锁粒度大并发度会比较低,同一时刻仅允许一个存或者取操作。实际上,基于数组的循环队列,利用 CAS 原子操作,可以实现非常高效的并发队列。这也是循环队列比链式队列应用更加广泛的原因。
队列应用
- 模拟现实世界中的队列,如售票柜台的队列以及其他先到先服务的场景。
- 计算客户在呼叫中心等待的时间。
- 异步数据的传输(文件输入输出、管道、嵌套字)。
- 操作系统中的优先级任务执行。
- 短信群体发送 应用的发布订阅模式
java 实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
| public class Queue {
private Object[] objQueue; private int maxSize; private int top; private int bottom; private int item;
public Queue(int size) { maxSize = size; objQueue = new Object[maxSize]; top = 0; bottom = -1; item = 0; }
public void add(Object obj){ if(item == maxSize){ throw new RuntimeException(obj+" add error, queue is full"); } if(bottom == maxSize-1){ bottom = -1; } objQueue[++bottom] = obj; item++; }
public Object out(){ if(item == 0){ throw new RuntimeException("queue is null"); } Object obj = objQueue[top]; objQueue[top] = null; top++; if(top == maxSize){ top = 0; } item--; return obj; }
private class NodeQueue<Object>{ private Object data;
private NodeQueue next;
public NodeQueue(Object data, NodeQueue next) { this.data = data; this.next = next; } } private NodeQueue queueTop; private NodeQueue queueBottom; private int size;
public Queue() { queueTop = null; queueBottom = null; size = 0; }
public void addNodeQueue(Object obj){ if(size == 0){ queueTop = new NodeQueue(obj,null); queueBottom = queueTop; }else{ NodeQueue<Object> nodeQueue = new NodeQueue(obj,null); queueBottom.next = nodeQueue; queueBottom = nodeQueue; } size ++; }
public Object removeNodeQueue(){ if(size == 0){ throw new RuntimeException("queue is null"); } NodeQueue nodeQueue = queueTop; queueTop = queueTop.next; nodeQueue.next = null; size--; return nodeQueue.data; }
@Override public String toString() { StringBuilder sb = new StringBuilder("{ "); for(NodeQueue nodeQueue = queueTop ; nodeQueue != null ; nodeQueue = nodeQueue.next){ sb.append(nodeQueue.data.toString()+" "); } return sb.toString()+"}"; }
public static void main(String[] args) { Queue queue = new Queue(); queue.addNodeQueue("123"); queue.addNodeQueue("abc"); queue.addNodeQueue("ddd"); System.out.println(queue); queue.removeNodeQueue(); System.out.println(queue); queue.removeNodeQueue(); queue.removeNodeQueue(); System.out.println(queue); } }
|