基础数据结构-队列
基本概念
思考:线程池里面任务满时,此时又来一个新任务,线程池是如何处理的?具体有哪些策略?这些策略又是如何实现的
队列:先进先出(FIFO),队列是一个特殊的线性表
队列定义:
队列只允许在表的前端进行删除操作,而在表的后端进行插入操作,是一种操作受限制的线性表。进行插入操作的是队尾,进行删除操作的是队头。没有元素时称为空队列。
队列中的数据元素称为队列元素,在队列中插入队列元素称为入队,从队列中删除元素称为出队。(可以类比于排队买票,不允许插队)
队列的分类:
1.顺序(单向)队列:(单向链表) 只在一端插入数据,在另一端删除数据。
2.循环(双向)队列: (循环链表) 每一端都可以进行插入数据和删除数据操作
队列的基本操作:
最基本的操作有两个:
1.入队(enqueue):放一个元素在队尾
2.出队(dequeue):从队头取一个元素
和栈一样,也是一种操作受限制的线性表数据结构,作为一种非常基础的数据结构,队列的应用也是非常广泛的,特别是一些具有某些额外特性的队列,比如循环队列、阻塞队列、并发队列。它们在很多偏底层系统、框架、中间件的开发中,起着关键性作用。
队列的实现方式:顺序队列&链式
链表可以无限扩容,一定要考虑内存问题,一定要加size的大小控制
实战:使用数组简单实现一个队列
package Queue;
import java.nio.channels.DatagramChannel;
public class ArrayQueue {
private int data[] ; //数据
private int head = 0;//头
private int tail = 0;//尾
private int n = 0; //数组大小
public ArrayQueue(int cap){
data = new int [cap];
n = cap;
}
public void push (int m){//入队
//判断这个队列是不是已经满了
if(tail == n){
return ;
}
data [tail] = m;
tail++;
//tail=(tail+1)%n; //循环队列与队列不同之处
}
public int pop(){ //出队
//要判断是不是为空
if (isEmpty()){
return -1;
}
int n = data[head];
head++;
//head=(head+1)%n; //循环队列与队列不同之处
return n;
}
public boolean isEmpty(){
if (head==tail)return true;
return false;
}
}
循环队列
怎么判断循环 队列已经满了?
1.加一个实际的size变量与最大空间n相比较
2.(tail+1)%n==head判断循环队列满了
怎么判断为空?
1.加一个实际的size变量,size为0;
2.tail==head
优先队列
回到排队场景,有些VIP用户总是可以插队。
抽奖时普通用户和VIP用户也不优先级不同
优先队列:在插入时排序
在入队时进行自定义排序!
public void push (int m){//入队
//判断这个队列是不是已经满了
if(tail == n){
return ;
}
data [tail] = m;
tail++;
//tail=(tail+1)%n; //循环队列与队列不同之处
}
阻塞队列
介绍:具有特殊性质的队列,在队列的基础上增加了阻塞操作,队列为空的时候,从队头取数据会被阻塞,直到有了数据才能返回;如果队列满了插入数据操作会被阻塞,直到有空闲位置时在插入数据,然后返回。
CPU:
线程池里面,当任务满时,又来一个新任务,线程池是如何处理的?具体有哪些策略?这些策略是如何实现的?
几种处理策略:
1.排队:阻塞队列。有空闲的时候再拿,如果公平的情况下,肯定是先进先出
就是队列,两种方式:一种是无限的排队队列(链表),还有一种是有界的(用数组实现的)。只处理我们开的空间大小,多了的继续抛出去。Integer.MAX=2^32-1,注意队列大小,小了不够用,打了浪费,在小型系统中,提前知道数据请求量是不大的,可以用无界的队列
2.丢弃:不处理了,直接抛出去