BlockingQueue 源码解析(JDK8)

BlockingQueue 源码解析(JDK8),第1张

BlockingQueue 源码解析(JDK8) 前言

本文隶属于专栏《100个问题搞定Java并发》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见100个问题搞定Java并发

正文 类注释
package java.util.concurrent;

import java.util.Collection;
import java.util.Queue;


public interface BlockingQueue extends Queue {

看起来注释好长,实际上就讲了下面几点:

1. BlockingQueue 是什么?

BlockingQueue 是一种队列,它还支持在检索元素时等待队列变为非空,在存储元素时等待队列中的空间变为可用的 *** 作。

2. BlockingQueue方法有哪些形式?

BlockingQueue方法有四种形式,有不同的处理 *** 作的方法,这些 *** 作不能立即满足,但在将来的某个时候可能会满足:

  1. 抛出异常
  2. 返回特殊值(null或false,取决于 *** 作)
  3. 线程无限期地阻塞当前线程,直到 *** 作成功
  4. 线程在放弃之前只阻塞给定的最大时间限制。

3. BlockingQueue不接受空元素

实现在尝试添加、放置或提供null时抛出NullPointerException。

null用作哨兵值,以指示轮询 *** 作失败。

4. 阻塞队列可能有容量限制

在任何给定的时间,它都可能有一个剩余容量,超过这个容量,就不能不阻塞地放置额外的元素。

没有任何内在容量约束的 BlockingQueue 始终报告 Integer.MAX_VALUE 值的剩余容量。

5. BlockingQueue 实现主要用于生产者-消费者队列,但还支持java.util.Collection 接口

因此,例如,可以使用 remove() 从队列中删除任意元素。

然而,这样的 *** 作通常不是非常有效地执行的,并且仅用于偶尔使用,例如当队列消息被取消时。

6. BlockingQueue 实现是线程安全的。

所有排队方法都使用内部锁或其他形式的并发控制以原子方式实现其效果。

但是,除非在实现中另有规定,否则批量收集 *** 作 addAll 、 containsAll 、 retainal 和 removeAll 不一定以原子方式执行。

因此,例如, addAll( c ) 在只添加 c 中的一些元素之后失败(引发异常)是可能的。

7. BlockingQueue 本质上不支持任何类型的 close 或 shutdown *** 作,以指示不再添加任何项目

这些特性的需求和使用往往取决于实现。

例如,一种常见的策略是生产商插入特殊的 end-of-stream 或“毒丸”(poison)对象,当消费者使用这些对象时,会相应地进行解释。

8. 使用示例

基于典型的生产者-消费者场景。

请注意, BlockingQueue 可以安全地用于多个生产者和多个消费者。

class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { queue.put(produce()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   Object produce() { ... }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     try {
       while (true) { consume(queue.take()); }
     } catch (InterruptedException ex) { ... handle ...}
   }
   void consume(Object x) { ... }
 }

 class Setup {
   void main() {
     BlockingQueue q = new SomeQueueImplementation();
     Producer p = new Producer(q);
     Consumer c1 = new Consumer(q);
     Consumer c2 = new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
   }
 }}
9. 内存一致性影响

与其他并发集合一样,在将对象放入 BlockingQueue 之前,线程中的 *** 作发生在另一个线程中从 BlockingQueue 访问或移除该元素之后的 *** 作之前。

add
    
    boolean add(E e);


如果可以在不违反容量限制的情况下立即将指定元素插入此队列,则会在成功时返回 true ,如果当前没有可用空间,则会引发 IllegalStateException 。

当使用容量受限队列时,通常最好使用 offer 。

异常
  1. IllegalStateException –如果此时由于容量限制而无法添加元素
  2. ClassCastException –如果指定元素的类阻止将其添加到此队列中
  3. NullPointerException –如果指定的元素为 null
  4. IllegalArgumentException –如果指定元素的某些属性阻止将其添加到此队列中。
offer
    
    boolean offer(E e);

如果可以在不违反容量限制的情况下立即将指定元素插入此队列,则在成功时返回 true ,如果当前没有可用空间,则返回 false 。

当使用容量受限队列时,此方法通常比 add 更可取,因为 add 只能通过抛出异常来插入元素。

异常
  1. ClassCastException –如果指定元素的类阻止将其添加到此队列中
  2. NullPointerException –如果指定的元素为 null
  3. IllegalArgumentException –如果指定元素的某些属性阻止将其添加到此队列中
put
    
    void put(E e) throws InterruptedException;

将指定的元素插入此队列,如有必要,等待空间变为可用。

异常
  1. InterruptedException–如果在等待时中断
  2. ClassCastException–如果指定元素的类阻止将其添加到此队列中
  3. NullPointerException–如果指定的元素为null
  4. IllegalArgumentException–如果指定元素的某些属性阻止将其添加到此队列中
offer + timeout
    
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;

将指定的元素插入此队列,如果需要空间可用,请等待指定的等待时间。

异常
  1. InterruptedException–如果在等待时中断
  2. ClassCastException–如果指定元素的类阻止将其添加到此队列中
  3. NullPointerException–如果指定的元素为null
  4. IllegalArgumentException–如果指定元素的某些属性阻止将其添加到此队列中
take
    
    E take() throws InterruptedException;

检索并删除此队列的头,如有必要,等待元素可用。

异常
  1. InterruptedException–如果在等待时中断
poll + timeout
    
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;

检索并删除此队列的头,如果需要元素变为可用,则等待指定的等待时间。

异常
  1. InterruptedException–如果在等待时中断
remainingCapacity
    
    int remainingCapacity();

返回此队列理想情况下(在没有内存或资源约束的情况下)可以不阻塞地接受的其他元素的数量,或者如果没有内在限制,返回 Integer.MAX_VALUE 值。

请注意,您不能总是通过检查 remainingCapacity 来判断插入元素的尝试是否成功,因为可能是另一个线程即将插入或删除元素。

remove
    
    boolean remove(Object o);

从该队列中删除指定元素的单个实例(如果存在)。

更正式地说,如果此队列包含一个或多个这样的元素,则删除元素e,使o.equals(e)。

如果此队列包含指定的元素,则返回true(如果此队列因调用而更改,则返回等效值)。

异常
  1. ClassCastException–如果指定元素的类与此队列不兼容(可选)
  2. NullPointerException–如果指定的元素为null(可选)
  3. UnsupportedOperationException–如果此集合不支持删除 *** 作
contains
    
    public boolean contains(Object o);

如果此队列包含指定的元素,则返回true。

更正式地说,当且仅当此队列包含至少一个元素e,使得o.equals(e)时,返回true。

异常
  1. ClassCastException–如果指定元素的类与此队列不兼容(可选)
  2. NullPointerException–如果指定的元素为null(可选)
drainTo
    
    int drainTo(Collection c);

从此队列中删除所有可用元素并将它们添加到给定集合。

此 *** 作可能比重复轮询此队列更有效。

尝试将元素添加到集合c时遇到的故障可能会导致在引发关联异常时元素既不在集合中,也不在集合中或同时在集合中。

尝试将队列排入自身会导致IllegalArgumentException。

此外,如果在 *** 作进行过程中修改了指定的集合,则此 *** 作的行为是未定义的。

异常
  1. UnsupportedOperationException–如果指定集合不支持添加元素
  2. ClassCastException–如果此队列元素的类阻止将其添加到指定集合中
  3. NullPointerException–如果指定的集合为null
  4. IllegalArgumentException–如果指定集合是此队列,或者此队列元素的某些属性阻止将其添加到指定集合中
drainTo + maxElements
    
    int drainTo(Collection c, int maxElements);
}

从该队列中最多移除给定数量的可用元素,并将它们添加到给定集合中。

尝试将元素添加到集合c时遇到的故障可能会导致在引发关联异常时元素既不在集合中,也不在集合中或同时在集合中。

尝试将队列排入自身会导致IllegalArgumentException。

此外,如果在 *** 作进行过程中修改了指定的集合,则此 *** 作的行为是未定义的。

异常
  1. UnsupportedOperationException–如果指定集合不支持添加元素
  2. ClassCastException–如果此队列元素的类阻止将其添加到指定集合中
  3. NullPointerException–如果指定的集合为null
  4. IllegalArgumentException–如果指定集合是此队列,或者此队列元素的某些属性阻止将其添加到指定集合中

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5437762.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-11
下一篇 2022-12-11

发表评论

登录后才能评论

评论列表(0条)

保存