java多线程与并发之java并发编程实践(八)

时间:2022-12-23 19:04:23
并发集合(二)
----------
Queue介绍

1.java.util.Queue<E>
public interface Queue<E>extends Collection<E>


2. java.util.concurrent.BlockingQueue<E>
public interface BlockingQueue<E>extends Queue<E>
支持两个附加操作的Queue,这两个操作是:获取元素时等待队列变为非空,以及存储元素时等待空间变得可用。 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(null 或false,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:

  抛出异常 特殊值 阻塞 超时
插入  add(e)  offer(e) put(e) offer(e, time, unit)
移除 remove()  poll() take()  poll(time, unit)
检查 element() peek() 不可用 不可用
BlockingQueue不接受null元素。试图add、put或offer一个null元素时,某些实现会抛出NullPointerException。null被用作指示poll 操作失败的警戒值。 
BlockingQueue可以是限定容量的。它在任意给定时间都可以有一个remainingCapacity,超出此容量,便无法无阻塞地put附加元素。没有任何内部容量约束的BlockingQueue总是报告Integer.MAX_VALUE的剩余容量。 
BlockingQueue实现主要用于生产者-使用者队列,但它另外还支持Collection接口。因此,举例来说,使用remove(x)从队列中移除任意一个元素是有可能的。然而,这种操作通常不会有效执行,只能有计划地偶尔使用,比如在取消排队信息时。 
BlockingQueue实现是线程安全的。所有排队方法都可以使用内部锁或其他形式的并发控制来自动达到它们的目的。然而,大量的Collection 操作(addAll、containsAll、retainAll 和 removeAll)没有必要自动执行,除非在实现中特别说明。因此,举例来说,在只添加了c中的一些元素后,addAll(c) 有可能失败(抛出一个异常)。 

3.java.util.Deque<E>
public interface Deque<E>extends Queue<E>
一个线性collection,支持在两端插入和移除元素。名称deque是“double ended queue(双端队列)”的缩写,通常读为“deck”。大多数 Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。 此接口定义在双端队列两端访问元素的方法。提供插入、移除和检查元素的方法。每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(null 或 false,具体取决于操作)。插入操作的后一种形式是专为使用有容量限制的 Deque 实现设计的;在大多数实现中,插入操作不能失败。 

4.java.util.concurrent.BlockingDeque<E>

public interface BlockingDeque<E>extends BlockingQueue<E>, Deque<E>

支持两个附加操作的Queue,这两个操作是:获取元素时等待双端队列变为非空;存储元素时等待双端队列中的空间变得可用。 BlockingDeque方法有四种形式,使用不同的方式处理无法立即满足但在将来某一时刻可能满足的操作:第一种方式抛出异常;第二种返回一个特殊值(null 或 false,具体取决于操作);第三种无限期阻塞当前线程,直至操作成功;第四种只阻塞给定的最大时间,然后放弃。

5.java.util.AbstractQueue<E>
public abstract class AbstractQueue<E>extends AbstractCollection<E>implements Queue<E>
此类提供某些Queue操作的骨干实现。此类中的实现适用于基本实现不允许包含null元素时。add、remove和element 方法分别基于offer、poll和peek方法,但是它们通过抛出异常而不是返回false或null来指示失败。

6.java.util.concurrent.ArrayBlockingQueue<E>
public class ArrayBlockingQueue<E>extends AbstractQueue<E>implements BlockingQueue<E>, Serializable
一个由数组支持的有界阻塞队列。此队列按FIFO(先进先出)原则对元素进行排序。队列的头部是在队列中存在时间最长的元素。队列的尾部 是在队列中存在时间最短的元素。新元素插入到队列的尾部,队列获取操作则是从队列头部开始获得元素。 
这是一个典型的“有界缓存区”,固定大小的数组在其中保持生产者插入的元素和使用者提取的元素。一旦创建了这样的缓存区,就不能再增加其容量。试图向已满队列中放入元素会导致操作受阻塞;试图从空队列中提取元素将导致类似阻塞。 
此类支持对等待的生产者线程和使用者线程进行排序的可选公平策略。默认情况下,不保证是这种排序。然而,通过将公平性 (fairness) 设置为true而构造的队列允许按照FIFO 顺序访问线程。公平性通常会降低吞吐量,但也减少了可变性和避免了“不平衡性”。 

7.java.util.ArrayDeque<E>
public class ArrayDeque<E>extends AbstractCollection<E>implements Deque<E>, Cloneable, Serializable
Deque接口的大小可变数组的实现。数组双端队列没有容量限制;它们可根据需要增加以支持使用。它们不是线程安全的;在没有外部同步时,它们不支持多个线程的并发访问。禁止null元素。此类很可能在用作堆栈时快于Stack,在用作队列时快于LinkedList

8.java.util.concurrent.ConcurrentLinkedQueue<E>
public class ConcurrentLinkedQueue<E>extends AbstractQueue<E>implements Queue<E>, Serializable
一个基于链接节点的*线程安全队列。此队列按照FIFO(先进先出)原则对元素进行排序。队列的头部是队列中时间最长的元素。队列的尾部是队列中时间最短的元素。新的元素插入到队列的尾部,队列获取操作从队列头部获得元素。当多个线程共享访问一个公共collection时,ConcurrentLinkedQueue是一个恰当的选择。此队列不允许使用null元素。

9.java.util.concurrent.DelayQueue<E extends Delayed>
public class DelayQueue<E extends Delayed>extends AbstractQueue<E>implements BlockingQueue<E>
Delayed元素的一个*阻塞队列,只有在延迟期满时才能从中提取元素。该队列的头部是延迟期满后保存时间最长的Delayed 元素。如果延迟都还没有期满,则队列没有头部,并且poll将返回 null。当一个元素的getDelay(TimeUnit.NANOSECONDS)方法返回一个小于等于0的值时,将发生到期。即使无法使用take或poll移除未到期的元素,也不会将这些元素作为正常元素对待。例如,size方法同时返回到期和未到期元素的计数。此队列不允许使用null元素。

10.java.util.concurrent.LinkedBlockingDeque<E>
public class LinkedBlockingDeque<E>extends AbstractQueue<E>implements BlockingDeque<E>, Serializable
一个基于已链接节点的、任选范围的阻塞双端队列。可选的容量范围构造方法参数是一种防止过度膨胀的方式。如果未指定容量,那么容量将等于Integer.MAX_VALUE。只要插入元素不会使双端队列超出容量,每次插入后都将动态地创建链接节点。

11.java.util.concurrent.LinkedBlockingQueue<E>
public class LinkedBlockingQueue<E>extends AbstractQueue<E>implements BlockingQueue<E>, Serializable
一个基于已链接节点的、范围任意的blocking queue。此队列按FIFO(先进先出)排序元素。队列的头部是在队列中时间最长
的元素。队列的尾部是在队列中时间最短的元素。新元素插入到队列的尾部,并且队列获取操作会获得位于队列头部的元素。链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低
。 可选的容量范围构造方法参数作为防止队列过度扩展的一种方法。如果未指定容量,则它等于Integer.MAX_VALUE。除非插入节点会使队列超出容量,否则每次插入后会动态地创建链接节点。

12.java.util.concurrent.PriorityBlockingQueue<E>
public class PriorityBlockingQueue<E>extends AbstractQueue<E>implements BlockingQueue<E>, Serializable
一个*阻塞队列,它使用与类PriorityQueue相同的顺序规则,并且提供了阻塞获取操作。虽然此队列逻辑上是*的,但是资源被耗尽时试图执行add操作也将失败(导致OutOfMemoryError)。此类不允许使用null元素。依赖自然顺序的优先级队列也不允许插入不可比较的对象这样做会导致抛出 ClassCastException)

13.java.util.PriorityQueue<E>
public class PriorityQueue<E>extends AbstractQueue<E>implements Serializable
一个基于优先级堆的*优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的Comparator进行排序,具体取决于所使用的构造方法。优先级队列不允许使用null元素。依靠自然顺序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)。 此队列的头是按指定排序方式确定的最小元素。如果多个元素都是最小值,则头是其中一个元素——选择方法是任意的。队列获取操作poll、remove、peek和element访问处于队列头的元素。 
优先级队列是*的,但是有一个内部容量,控制着用于存储队列元素的数组大小。它通常至少等于队列的大小。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。