JDK1.8源码解读之 BlockingQueue

249 阅读5分钟

前言

  • {@link java.util.Queue}另外还支持以下操作:
  • 在检索元素时等待队列变为非空,并在存储元素时等待队列中的空间变为可用。
  • {@code BlockingQueue}方法有四种形式,它们以不同的方式处理操作,这些方法无法立即满足,但将来可能会满足:
  • 一种抛出异常,
  • 第二种返回一个特殊值({@code null}或{@code false},具体取决于操作),
  • 第三个无限期阻塞当前线程,直到操作成功为止;
  • 第四个阻塞仅一个给定的最大时间限制,然后再放弃。
  • {@code BlockingQueue}不接受{@code null}元素。
  • 实现尝试对{@code add},{@code put}或{@code offer}一个{@code null}进行尝试时,抛出{@code NullPointerException}。
  • {@code null}用作标记值,以指示{@code poll}操作失败。
  • {@code BlockingQueue}可能受容量限制。
  • 在任何给定时间,它都可能具有{@code leftCapacity},超过该值之前,任何其他元素都不能被{@code put}阻塞。
  • 没有任何内部容量约束的{@code BlockingQueue}始终报告{@code Integer.MAX_VALUE}的剩余容量。
  • {@code BlockingQueue}实现被设计为主要用于生产者-消费者队列,但还支持{@link java.util.Collection}接口。
  • 因此,例如,可以使用{@code remove(x)}从队列中删除任意元素。
  • 但是,这样的操作通常不能非常有效地执行,并且仅用于偶尔的使用,例如在取消排队的消息时。
  • {@code BlockingQueue}实现是线程安全的。
  • 所有排队方法都可以使用内部锁或其他形式的并发控制来原子地实现其效果。
  • 但是,除非在实现中另行指定,否则不一定要自动执行批量Collection操作{@code addAll},{@code containsAll},{@code keepAll}和{@code removeAll}。
  • 因此,例如,仅在{@code c}中添加一些元素之后,{@code addAll(c)}可能会失败(引发异常)。
  • {@code BlockingQueue}本质上不支持任何类型的“关闭”或“关闭”操作,以表示不会再添加任何项目。
  • 这些功能的需求和使用往往取决于实现。例如,一种常见的策略是让生产者插入特殊的流尾对象或有毒对象,这些特殊对象在被消费者拿走时会被相应地解释。
  • 内存一致性影响:与其他并发集合一样,
  • 在将对象放入{@code BlockingQueue} 在访问或删除之后发生的先于操作的线程中的操作。
  • 来自另一个线程中{@code BlockingQueue}的元素的元素。

源码

package java.util.concurrent;
 public interface BlockingQueue<E> extends Queue<E> {
    /**
     * 如果可以立即将指定的元素插入此队列,而不会违反容量限制,则在成功时返回{@code true},
     * 如果当前没有可用空间,则抛出{@code IllegalStateException}。
     * 使用容量受限的队列时,通常最好使用{@link #offer(Object)offer}。
     */
    boolean add(E e);

    /**
     * 如果可以立即将指定的元素插入此队列,而不会违反容量限制,则在成功时返回{@code true},
     * 如果当前没有可用空间,则返回{@code false}。
     * 当使用容量受限的队列时,此方法通常比{@link #add}更可取,后者只能通过引发异常而无法插入元素。
     */
    boolean offer(E e);

    /**
     * 将指定的元素插入此队列,如有必要,等待空间可用。
     */
    void put(E e) throws InterruptedException;

    /**
     * 将指定的元素插入此队列,直到必要时等待指定的等待时间以使空间可用。
     */
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;

    /**
     * 检索并删除此队列的头,如有必要,请等待直到元素可用。
     */
    E take() throws InterruptedException;

    /**
     * 检索并除去此队列的头,如果有必要使元素可用,则等待指定的等待时间。
     */
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;

    /**
     * 返回此队列理想情况下(在没有内存或资源限制的情况下)可以无阻塞接受的其他元素的数量;
     * 如果没有内部限制,则返回{@code Integer.MAX_VALUE}。
     * 请注意,您无法始终通过检查{@code missingCapacity}来判断插入元素的尝试是否会成功,因为可能是另一个线程即将插入或删除元素的情况。
     */
    int remainingCapacity();

    /**
     * 从该队列中删除指定元素的单个实例(如果存在)。
     * 更正式地说,如果此队列包含一个或多个这样的元素,则删除元素{@code e},使{@code o.equals(e)}。
     * 如果此队列包含指定的元素(或者等效地,如果此队列由于调用而更改),则返回{@code true}。
     */
    boolean remove(Object o);

    /**
     * 如果此队列包含指定的元素,则返回{@code true}。
     * 更正式地说,当且仅当此队列包含至少一个元素{@code e}使得{@code o.equals(e)}时,才返回{@code true}。
     */
    public boolean contains(Object o);

    /**
     * 从此队列中删除所有可用元素,并将它们添加到给定的集合中。
     * 此操作可能比重复轮询此队列更有效。
     * 尝试将元素添加到集合{@code c}时遇到故障,可能会导致在引发关联异常时元素既不在两个集合中,又不在两个集合中。
     * 尝试排空队列本身会导致{@code IllegalArgumentException}。
     * 此外,如果在操作进行过程中修改了指定的集合,则此操作的行为不确定。
     */
    int drainTo(Collection<? super E> c);

    /**
     * 从此队列中最多移除给定数量的可用元素,并将它们添加到给定的集合中。
     * 尝试将元素添加到集合{@code c}时遇到故障,可能会导致在引发关联异常时元素既不在两个集合中,又不在两个集合中。
     * 尝试排空队列本身会导致{@code IllegalArgumentException}。
     * 此外,如果在操作进行过程中修改了指定的集合,则此操作的行为不确定。 
     */
    int drainTo(Collection<? super E> c, int maxElements);
}