Data Structures and Algorithms (VI) - queue

First, the learning syllabus

  • Define a queue, classifications, the basic method
  • Implementation code of the queue
  • The underlying queue (array, linked list)
  • Classification queue: the queues, circular queue

Second, the queue

  1. Defined queues: one advanced, first out operation of constrained linear list data structure , which contains the enqueue the enqueue () and dequeue () two basic operations;

01queue-base

As a very basic data structures, application queue is also very wide, especially some queue with certain additional features, such as a circular queue blocking queue, concurrent queue. They develop a lot of partial underlying system, the frame, the middleware, plays a key role. For example, high performance queue Disruptor, Linux ring buffer, have used the cycle concurrent queue; Java concurrent use ArrayBlockingQueue and contracting to achieve a fair locks, etc.

  1. java achieve a Queue (array)

// 用数组实现的队列
public class ArrayQueue {
  // 数组:items,数组大小:n
  private String[] items;
  private int n = 0;
  // head表示队头下标,tail表示队尾下标
  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;
    items[tail] = item;
    ++tail;
    return true;
  }

  // 出队
  public String dequeue() {
    // 如果head == tail 表示队列为空
    if (head == tail) return null;
    // 为了让其他语言的同学看的更加明确,把--操作放到单独一行来写了
    String ret = items[head];
    ++head;
    return ret;
  }
}

The above basic code meets a queue: application generally relates to storage space, the condition judging enqueue, dequeue condition judgment, is insufficient, when most of the array is filled after an address, even if the head is less than the tail pointer, can not be then into the team, and this time you need data movement when, after inserting a new element, but not every team has the operation, we need to move data, we simply no free space in the queue, it triggers a need to focus moving operation, this time into the team's need for enqueue () function to transform:


   // 入队操作,将item放入队尾
  public boolean enqueue(String item) {
    // tail == n表示队列末尾没有空间了
    if (tail == n) {
      // tail ==n && head==0,表示整个队列都占满了
      if (head == 0) return false;
      // 数据搬移
      for (int i = head; i < tail; ++i) {
        items[i-head] = items[i];
      }
      // 搬移完之后重新更新head和tail
      tail -= head;
      head = 0;
    }
    
    items[tail] = item;
    ++tail;
    return true;
  }

schematic diagram:

  1. Based list queue implementation method
  • head pointer and the tail pointer. They point to the first node and the last linked list node. As shown, when the team, tail-> next = new_node, tail = tail-> next; time dequeued, head = head-> next.

  1. Circular queue
  • Array-based implementation which, when the tail = n when data needs to be migrated, the loss will fall performance, there is no way to avoid it? That is a circular queue.
  • 04cycleQueue
  • 图中这个队列的大小为 8,当前 head=4,tail=7。当有一个新的元素 a 入队时,我们放入下标为 7 的位置。但这个时候,我们并不把 tail 更新为 8,而是将其在环中后移一位,到下标为 0 的位置。当再有一个元素 b 入队时,我们将 b 放入下标为 0 的位置,然后 tail 加 1 更新为 1。

完成循环队列的代码,最关键的是:确定好队空和队满的判定条件,队满的判断条件是 tail == n,队空的判断条件是 head == tail;

05cyclequeue

就像我图中画的队满的情况,tail=3,head=4,n=8,所以总结一下规律就是:(3+1)%8=4。多画几张队满的图,你就会发现,当队满时,(tail+1)%n=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. 阻塞队列与并发队列

阻塞队列其实就是在队列基础上增加了阻塞操作。简单来说,就是在队列为空的时候,从队头取数据会被阻塞。因为此时还没有数据可取,直到队列中有了数据才能返回;如果队列已经满了,那么插入数据的操作就会被阻塞,直到队列中有空闲位置后再插入数据,然后再返回。06queue

阻塞队列存在并发的问题:

07queue

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

三、引入问题:线程池没有空闲线程时,新的任务请求线程资源时,线程池该如何处理?各种处理策略又是如何实现的呢?

  • 我们一般有两种处理策略。第一种是非阻塞的处理方式,直接拒绝任务请求;另一种是阻塞的处理方式,将请求排队,等到有空闲线程时,取出排队的请求继续处理。那如何存储排队的请求呢?
  • We want fair treatment of requests for each queue, advanced, first serve, so this queue data structure is very suitable to store queued requests. As we have said, there is a queue based on linked lists and arrays based on these two implementations. Both implementations for queued requests, what difference does it make?
  • Based implementation of a linked list, you can achieve a support unlimited line of unbounded queue (unbounded queue), but may result in too many requests are queued request response processing time is too long. So, for more sensitive response time of the system, based on an infinite queue thread pool linked list implementation is not appropriate.
  • The queue on a bounded (bounded queue), the finite size of the array to achieve the queue, the thread pool queued requests exceeds the size of the queue, the next request will be denied, in this way the response time sensitive systems , relatively more reasonable. However, a reasonable set of queue size, is very luxurious. Queue is too large to too many pending requests, the queue is too small will lead to not make full use of system resources, maximize performance.
  • In addition to the previously mentioned application queue requests queued thread pool scene outside the queue can be applied in any limited resource pool for queuing request, such as a database connection pool and the like. In fact, for most limited resource scenario, when there is no free resources, can be implemented basically by the request queue "Queue" this data structure.

Fourth, after-school thinking

  1. In addition to the thread pool this pool structure will be used queuing request, you also know what a similar cell structure or scene will be used queuing queue request it?
  2. Today talked about concurrent queue on how to achieve lock-free concurrent queue, there are a lot of online discussion. On this issue, how do you see it?

Guess you like

Origin www.cnblogs.com/liweiweicode/p/11966228.html