ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

06_队列

2022-06-26 10:02:21  阅读:123  来源: 互联网

标签:head return String 队列 item tail 06


06_队列

什么是队列

先进者先出,这就是典型的队列结构。

栈的操作:入栈(push())、出栈(pop())

队列的操作:入队(enqueue())、出队(dequeue())

队列和栈一样,也是一种操作受限的线性表数据结构。

顺序队列和链式队列

基于数组实现——顺序队列

基于链表实现——链式队列

顺序队列的实现

public class ArrayQueue {
 private String[] items;
 private int n = 0;
 private int head = 0;
 private int tail = 0;
 
 // 申请一个大小为capacity的数组
 public ArrayQueue(int capacity) {
   items = new String[capacity];
   n = capacity;
}
 
 // 入队
 public boolean enqueue(String item) {
   // 如果tail = n则表示队列已经满了
   if (tail == n) return false;
   item[tail] = item;
   ++tail;
   return true;
}
 
 // 出队
 public String dequeue() {
   // 如果head = tail 表示队列为空
   if (head == tail) return null;
   String ret = items[head];
   ++head;
   return ret;
}
}

操作示意图:

弊端:随着不停地进行入队、出队操作,head和tail都会持续向后移动。当tail移动到最右边,即使数组中还有空闲空间,也无法继续往队列中添加数据了。

解决方法:进行数据搬迁。

在入队之前进行判断: 修改入队代码:

public boolean enqueue(String item) {
 // 当tail == n && head == 0的时候,表示整个队列都被占满了
 // 否则进行数据搬迁
 if (tail == n) {
   if (head == 0) return false;
   for (int i = head; i < tail; ++i) {
     item[i - head] = items[i];
  }
   // 搬迁完之后重新更新Head和tail
   tail -= head;
   head = 0;
}
 item[tail] = item;
 ++tail;
 return true;
}

链式队列的实现

道理同上,只是多了一个指针的概念

循环队列

解决数据搬迁的问题

结构示意图:

关键:确定好队空和队满的判定条件

队列为空的判断条件:

head == tail

队列满的判断条件:

(tail + 1) % n == head

代码示例:

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 = capaticy;
}
 
 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;
}
}

阻塞队列和并发队列

阻塞队列

其实就是在队列的基础上增加了阻塞的操作。

典型:"生产者-消费者模型"

在队列为空的时候,从队头取数据会被阻塞;

如果队列已经满了,那么插入数据的操作就会被阻塞,知道队列中有空闲位置后再插入数据,然后再返回。

结构示意图:

并发队列

即线程安全的队列。最简单的实现方式就是直接在enqueue()、dequeue()方法上加锁,但是锁粒度大并发度会比较低,同一时刻仅允许一个存或者取操作。实际上,基于数组的循环队列,利用CAS原子操作,可以实现非常高效的并发队列。这也是循环队列比链式队列应用更加广泛的原因。

问题

当线程池没有空闲线程时,新的任务请求线程资源时,线程池该如何处理?各种处理策略是如何实现的?

一般两种处理策略:

  1. 非阻塞处理:直接拒绝任务请求。

  2. 阻塞排队:将请求进行排队,等到有空闲线程时,取出排队的请求继续处理

    如何存储排队请求:

    • 基于数组实现的有界队列,队列大小有限,所以线程池中排队的请求超过队列大小时,接下来的请求就会被拒绝,这种方式对响应时间敏感的系统更加合理。

    • 基于链表实现的无界队列,但是可能会导致过多的请求排队等待,请求处理的响应时间过长。

实际上,对于大部分资源有限的场景,当没有空闲资源时,基本上都可以通过“队列”这种数据结构来实现请求排队。

总结

 

 

 

标签:head,return,String,队列,item,tail,06
来源: https://www.cnblogs.com/l12138h/p/16413010.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有