java queue - detailed analysis of queue

Queue: Basically, a queue is a first-in, first-out (FIFO) data structure

The Queue interface is at the same level as List and Set, and both inherit the Collection interface. LinkedList implements the Deque interface.

 

Implementation of Queue


1. LinkedList of unimplemented blocking interface: Implemented java.util.Queue interface and java.util.AbstractQueue interface
  Built-in non-blocking queue:  PriorityQueue  and  ConcurrentLinkedQueue
  PriorityQueue and ConcurrentLinkedQueue classes add two concrete collection implementations in Collection Framework. 
  The PriorityQueue class essentially maintains an ordered list. Elements added to the Queue are positioned according to their natural ordering (through their java.util.Comparable implementation) or according to the java.util.Comparator implementation passed to the constructor.
  ConcurrentLinkedQueue is a linked node-based, thread-safe queue. Concurrent access does not require synchronization. Because it adds elements to the tail of the queue and removes them from the head, ConcurrentLinkedQueue's shared access to a common collection works just fine as long as it doesn't need to know the size of the queue. Gathering information about the size of the queue would be slow and would require traversing the queue.


2) Implement the blocking interface: The
  BlockingQueue interface and five blocking queue classes are added to java.util.concurrent. It is essentially a FIFO data structure with a little twist. Instead of immediately adding or removing elements from the queue, the thread performing the operation blocks until space or an element becomes available.
Each of the five queues provides different:
   * ArrayBlockingQueue  : A bounded queue backed by an array.
  * LinkedBlockingQueue  : An optional bounded queue backed by linked nodes.
  * PriorityBlockingQueue  : An unbounded priority queue backed by a priority heap.
  * DelayQueue  : A time-based scheduling queue backed by a priority heap.
  * SynchronousQueue  : A simple aggregation (rendezvous) mechanism utilizing the BlockingQueue interface.

 

 

 

The following table shows the operation of blocking queue in jdk1.5:

 

  add         adds an element index If the queue is full, throws a IIIegaISlabEepeplian exception remove    removes and returns the element at the head of the queue If the queue is empty, throws a NoSuchElementException exception  element returns the element at the head of the queue If the queue is empty, then Throws a NoSuchElementException, offer     adds an element and returns true if the queue is full, returns false poll      removes and returns the element at the head of the queue if the queue is empty, returns null peek      returns the element at the head of the queue if the queue is empty , then return null put        add an element If the queue is full, then block take         remove and return the element at the head of the queue If the queue is empty, block
  
  
     
      
    
    
  

 

remove, element, offer, poll, and peek actually belong to the Queue interface. 

 

Operations that block queues can be divided into three categories based on how they respond: aad, remove, and element operations throw exceptions when you try to add elements to a full queue or get elements from an empty queue. Of course, in a multithreaded program, the queue can become full or empty at any time, so you might want to use the offer, poll, peek methods. These methods simply give an error message instead of throwing an exception when the task cannot be completed.

 

Note: The poll and peek methods return null on error. Therefore, it is not legal to insert a null value into the queue

 

最后,我们有阻塞操作put和take。put方法在队列满时阻塞,take方法在队列空时阻塞。

 

 

LinkedBlockingQueue的容量是没有上限的(说的不准确,在不指定时容量为Integer.MAX_VALUE,不要然的话在put时怎么会受阻呢),但是也可以选择指定其最大容量,它是基于链表的队列,此队列按 FIFO(先进先出)排序元素。


ArrayBlockingQueue在构造时需要指定容量, 并可以选择是否需要公平性,如果公平参数被设置true,等待时间最长的线程会优先得到处理(其实就是通过将ReentrantLock设置为true来 达到这种公平性的:即等待时间最长的线程会先操作)。通常,公平性会使你在性能上付出代价,只有在的确非常需要的时候再使用它。它是基于数组的阻塞循环队 列,此队列按 FIFO(先进先出)原则对元素进行排序。


PriorityBlockingQueue是一个带优先级的 队列,而不是先进先出队列。元素按优先级顺序被移除,该队列也没有上限(看了一下源码,PriorityBlockingQueue是对 PriorityQueue的再次包装,是基于堆数据结构的,而PriorityQueue是没有容量限制的,与ArrayList一样,所以在优先阻塞 队列上put时是不会受阻的。虽然此队列逻辑上是无界的,但是由于资源被耗尽,所以试图执行添加操作可能会导致 OutOfMemoryError),但是如果队列为空,那么取元素的操作take就会阻塞,所以它的检索操作take是受阻的。另外,往入该队列中的元 素要具有比较能力。


DelayQueue(基于PriorityQueue来实现的)是一个存放Delayed 元素的无界阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的 Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且poll将返回null。当一个元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一个小于或等于零的值时,则出现期满,poll就以移除这个元素了。此队列不允许使用 null 元素。

 

 一个例子:

package com.yao;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class BlockingQueueTest {
 /**
 定义装苹果的篮子
  */
 public static class Basket{
  // 篮子,能够容纳3个苹果
  BlockingQueue<String> basket = new ArrayBlockingQueue<String>(3);

  // 生产苹果,放入篮子
  public void produce() throws InterruptedException{
   // put方法放入一个苹果,若basket满了,等到basket有位置
   basket.put("An apple");
  }
  // 消费苹果,从篮子中取走
  public String consume() throws InterruptedException{
   // get方法取出一个苹果,若basket为空,等到basket有苹果为止
   String apple = basket.take();
   return apple;
  }

  public int getAppleNumber(){
   return basket.size();
  }

 }
 // 测试方法
 public static void testBasket() {
  // 建立一个装苹果的篮子
  final Basket basket = new Basket();
  // 定义苹果生产者
  class Producer implements Runnable {
   public void run() {
    try {
     while (true) {
      // 生产苹果
      System.out.println("生产者准备生产苹果:" 
        + System.currentTimeMillis());
      basket.produce();
      System.out.println("生产者生产苹果完毕:" 
        + System.currentTimeMillis());
      System.out.println("生产完后有苹果:"+basket.getAppleNumber()+"个");
      // 休眠300ms
      Thread.sleep(300);
     }
    } catch (InterruptedException ex) {
    }
   }
  }
  // 定义苹果消费者
  class Consumer implements Runnable {
   public void run() {
    try {
     while (true) {
      // 消费苹果
      System.out.println("消费者准备消费苹果:" 
        + System.currentTimeMillis());
      basket.consume();
      System.out.println("消费者消费苹果完毕:" 
        + System.currentTimeMillis());
      System.out.println("消费完后有苹果:"+basket.getAppleNumber()+"个");
      // 休眠1000ms
      Thread.sleep(1000);
     }
    } catch (InterruptedException ex) {
    }
   }
  }

  ExecutorService service = Executors.newCachedThreadPool();
  Producer producer = new Producer();
  Consumer consumer = new Consumer();
  service.submit(producer);
  service.submit(consumer);
  // 程序运行10s后,所有任务停止
  try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
  }
  service.shutdownNow();
 }
 public static void main(String[] args) {
  BlockingQueueTest.testBasket();
 }
}

 出处:https://www.cnblogs.com/lemon-flm/p/7877898.html

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324714014&siteId=291194637