队列:
1,CPU 分配资源,其底层的数据结构为队列
2,队列基本操作
1)入队 enqueue(),从队尾加入一个元素
2) 出队dequeue(),从队列头部取一个元素
3,和栈一样,是操作受限的线性表数据结构,应用范围可分为
1) 循环队列
2) 阻塞队列
3) 并发队列
多用于偏底层系统,框架,中间件开发。
Disruptor 、Linux 环形缓存,都用到了循环并发队列
Java concurrent 利用了 ArrayBlockQueue 实现公平锁
4,组成:
1)数组实现的队列为顺序队列
public class ArrayQueue {
private string[] items;
private int n = 0;
private int head = 0;
private int tail = 0;
public ArrayQueue(int capacity){
items = new String[capacity];
n = capacity;
}
// 入队
public boolean enqueue(){
if(tail == n) return false;
items[tail++] = item;
return true;
}
// 出队
public String dequeue(){
if(head == tail) return null;
String ret = items[head++];
return ret;
}
}
2)链表实现的队列为链式队列
5,发现问题:
1)当 tail 移动到最右边的时候,head 移动到中间位置时,数组有空余空间,但是不能插入数据。因此在入队的时候需要触发数据搬移的操作
public boolean enqueue(String item){
if(tail == n){
if(head == 0) return false;
for(int i = head; i < tail; i++){
items[i - head] = items[i];
}
tail-=head;
head = 0;
}
items[tail++] = item;
return true;
}
6,循环队列
public class CircularQueue {
private String[] items;
private int n = 0;
private int head = 0;
private int tail = 0;
public CircularQueue(int capacity){
items = new String[capacity];
n = capacity;
}
// 入队
public boolean enqueue(String item){
if((tail + 1) % n == head) return false;
items[tail] = item;
tail = (tail + 1) % n;
return true;
}
// 出队
public String dequeue(){
if(head == tail) return null;
String ret = items[head];
head = (head + 1) % n;
return ret;
}
}
7,阻塞队列
1)阻塞队列其实就是在队列基础上增加了阻塞操作,简单来说,就是在队列为空的时候,从队头取数据会被阻塞。因为此时还没有数据可取,直到队列中有了数据才能返回;如果队列已经满了,那么插入数据的操作就会被阻塞,直到队列中有空闲位置后再插入数据,然后再返回。
2)基于链表的实现方式,可以支持一个无限排队的误解队列。针对响应时间敏感的系统,不合适。然而使用基于数组的有界队列,在队列大小的选择也是很讲究的。
8,并发队列,在 enqueue() , dequeue() 方法加锁。