java-数据结构-队列

类体系

这里写图片描述
这里写图片描述

java.util.Queue

Summary of Queue methods


Throws exception
Returns special value


Insert
{@link Queue#add add(e)}
{@link Queue#offer offer(e)}


Remove
{@link Queue#remove remove()}
{@link Queue#poll poll()}


Examine
{@link Queue#element element()}
{@link Queue#peek peek()}


保持元素优先处理
除了基本的集合操作外,队列提供额外的插入 提取和检查操作
这些操作的每一种都存在两种形式:

1、如果操作失败 会抛异常

Insert
{@link Queue#add add(e)}

Remove
{@link Queue#remove remove()}

Examine
{@link Queue#element element()}

2、返回一个特殊值 如 null 或者false

Insert
{@link Queue#offer offer(e)}

Remove
{@link Queue#poll poll()}

{@link Queue#peek peek()}

插入操作的另一种形式专门和容量限制 Queueue
在大多数实现中,插入操作不能失败

典型的队列,但不一定是,在A中的顺序元素FIFO(先进先出)方式。
例外情况是优先级队列,它根据提供的元素排序比较器,或元素的自然排序,以及LIFO队列(或堆栈顺序元素LIFO(后进先出)。

无论使用的顺序是什么,队列的head 在调用remove poll 的时候移除
在FIFO 队列中 所有新增元素加在队列尾部
Queue每种实现必须制定它的顺序属性

offer 尽可能插入元素 否则返回 false
不同于Collection add 加入元素失败 仅仅通过抛出unchecked exception

当失败是一种常态 offer 被设计来使用
而不是发生异常
例如 一个固定大小或者边界的队列

remove
poll
方法 移除和返回队列的头部
准确的说 哪个元素从队列中移除 是一个队列排序策略的函数
不同于实现

remove 和 poll 方法仅仅在他们行为上的不同
当队列是空的
remove 方法抛出异常
poll 方法返回null

element()和peek() 方法返回 但不移除 队列头部

接口不定义blocking queue方法 在并发编程中

这些方法 等待元素去出现或者空间去变成可用
定义在blockingQueue 接口

Queue 不允许插入空值
尽管一些实现
如linkedlist 允许插入空值

空值不应该插入到队列中
null是可以被用作特殊返回值 通过 poll 表明 队列是空的

Queue没有定义基于元素方法的版本 equals hashcode
但是继承了唯一基础版本来自Object
因为队列没有很好地定义唯一基础相等性 给同样的元素 但是不同的顺序属性


java.util.concurrent.BlockingQueue

增强了Queue
支持等待队列成为非空当获取一个元素的时候,
等待队列可用空间当存储一个元素的时候

BlockingQueue 方法有四种形式 不同的处理方式不能立即满足,但是可以在未来的某个时刻满足:
1、抛出异常
add、remove、element、element()

2、根据操作,返回特殊值 null 或者false
offer poll peek

3、阻塞当前线程 直到操作成功;
put take not applicable

4、阻塞在给定的最大时间限制范围内 给予之前
offer(Object, long, TimeUnit) offer(e, time, unit)}
poll(long, TimeUnit) poll(time, unit)}
not applicable

阻塞队列不接受null元素实现
抛出空指针尝试去add put offer 一个null值

null被用作一个敏感值表示poll 操作失败

阻塞队列可能是容量受限的 在任何给定时间可能有剩余容量 除此之外 没有额外的元素能被put而不阻塞
没有任何固定容量限制报告一个Integer.Max_Value的剩余容量

BlockingQueue被设计成用于生产者消费者队列,同时支持Collection接口,
它可以从队列中移除任意元素用remove(x),然而,not这种操作不是很有效,仅用于偶尔使用,例如取消排队消息时

所有Queue方法内部使用原子效应,使用锁或其他形式的并发控制。然而,
大批量操作如addAll ContainsAll retainAll 和removeAll 必须进行原子化,除非指定
在其他实现中。因此,有可能,例如allAll在添加后失败(抛出异常),

本质上支持任何类型的“关闭”或“关机”操作指示将不再添加任何项目。
需求与使用这样的特征往往是依赖于实现的。例如,A常见的策略是生产者插入特殊endofstream。
或者poison对象,即当消费者采取相应的解释。

基于典型生产者-消费者情景的使用示例
BlockingQueue 能安全地被多个producers和多个consumers使用

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();
  }
}}

记忆一致性效应:与其他并发集合一样,线程中的动作优先于将对象放入一个阻塞队列,
MemoryVisibility
happend-before
从阻塞队列访问或移除该元素之后的动作 用另一个线程。

猜你喜欢

转载自blog.csdn.net/qq_16038125/article/details/80370936