队列知识点

前言

cpu的资源是有限的,任务处理的速度和线程的个数不是线性相关。相反,过多的线程反而会导致cpu频繁切换,处理性能下降。
当我们向固定大小的线程池请求一个线程时,线程池中没有空闲的资源了,这个时候线程池如何处理请求。这时候我们引入了队列这个数据结构。

1.当我们想对顶大小的线程池中请求一个线程时候,如果线程池中没有空闲资源了,这个时候线程池如何处理这个请求?拒绝请求还是排队请求?

队列的应用很广泛,比如循环队列、阻塞队列、并发队列。
高性能队列disruptor、linux环形存储
java concurrent利用arrayblockingqueue实现公平锁

循环队列

  • 循环队列的难点在于确定队空和队满的判定条件。
    循环队列tail指向的位置上式没有存储数据的,因此循环队列会浪费一个数组的存储空间。
    队列满的条件为:(tail+1)%n==head
    队列空的条件为:tail==head
    正是因为队满和队空的条件需要不相同,所以循环队列会浪费一个存储单元。
public class CircularQueue {
  // 数组:items,数组大小:n
  private String[] items;
  private int n = 0;
  // head 表示队头下标,tail 表示队尾下标
  private int head = 0;
  private int tail = 0;

  // 申请一个大小为 capacity 的数组
  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() {
    // 如果 head == tail 表示队列为空
    if (head == tail) return null;
    String ret = items[head];
    head = (head + 1) % n;
    return ret;
  }
}

阻塞队列和并发队列

  • 1.阻塞队列:在队列的基础上增加了阻塞操作,当队列为空的时候,从队头取数据会被阻塞。如果队列已经满了,那么插入数据的操作会被阻塞,直到队伍中有空闲位置再插入数据,然后再返回。
  • 2.上面的定义是一个典型的生产者-消费者模型。当生产者的数据生产过快,存储数据的队列很快就满了这是生产者就要阻塞等待,直到消费者消费了数据,生产者才会继续生产。
  • 3.并发队列,最简单直接的方式在enqueue和的queue的方法上枷锁。

问题:线程池没有空闲线程时,新的任务请求线程资源时,线程池该如何处理?

  • 第一种是非阻塞的处理方式,直接拒绝任务请求;另一种是阻塞的处理方式,等优空闲线程的时候,去除排队的请求继续处理。

问题:基于链表和数组实现等待队列的区别?

*链表:实现了一个无限排队的队列,但是过多等待请求会是请求处理的响应时间过长,基于链表实现的无限排队是不合适的。
*基于数组:队列大小有限,队列太大等待请求太多,队列太小无法充分利用系统资源,发挥最大性能。
队列可以应用在任何有限资源池中,用于排队请求,比如数据库连接池等。对于大部分资源有限的场景,当没有空闲资源时,基本上都可以通过队列实现请求排队。

猜你喜欢

转载自blog.csdn.net/qq_22152499/article/details/89069420