一、Queue

Queye接口体系图

体系分析

Deque实现类:ArrayDequeLinkedList(数组和链表实现双向队列)

BlockingDeque实现类:LinkedBlockingDeque(链表实现阻塞双向队列)

BlockingQueue实现类:ArrayBlockingQueue,LinkedBlockingQueue,PriorityBlockingQueue,SynchronousQueue,DelayQueue

Queue源码

public interface Queue<E> extends Collection<E> {  //jdk1.5
boolean add(E e);
boolean offer(E e);
E remove();
E poll();
E element();
E peek();
}

在处理元素前用于保存元素的 collection.除了基本的 Collection 操作外,队列还提供其他的插入、提取和检查操作.每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(nullfalse,具体取决于操作).插入操作的后一种形式是用于专门为有容量限制的 Queue 实现设计的;在大多数实现中,插入操作不会失败.

Queue 接口并未定义阻塞队列的方法,而这在并发编程中是很常见的.BlockingQueue 接口定义了那些等待元素出现或等待队列中有可用空间的方法,这些方法扩展了此接口.

二、Deque

一个线性 collection,支持在两端插入和移除元素.名称 deque 是“double ended queue(双端队列)”的缩写.

此接口定义在双端队列两端访问元素的方法.提供插入、移除和检查元素的方法.每种方法都存在两种形式:一种形式在操作失败时抛出异常,另一种形式返回一个特殊值(nullfalse,具体取决于操作).插入操作的后一种形式是专为使用有容量限制的 Deque 实现设计的;在大多数实现中,插入操作不能失败.

下表总结了上述 12 种方法:

此接口扩展了 Queue 接口.在将双端队列用作队列时,将得到 FIFO(先进先出)行为.将元素添加到双端队列的末尾,从双端队列的开头移除元素.从 Queue 接口继承的方法完全等效于 Deque 方法,如下表所示:

双端队列也可用作 LIFO(后进先出)堆栈.应优先使用此接口而不是遗留 Stack 类.在将双端队列用作堆栈时,元素被推入双端队列的开头并从双端队列开头弹出.堆栈方法完全等效于 Deque 方法,如下表所示:

此接口提供了两种移除内部元素的方法:removeFirstOccurrenceremoveLastOccurrence.注意,在将双端队列用作队列或堆栈时,peek 方法同样正常工作;无论哪种情况下,都从双端队列的开头抽取元素.

三、BlockingQueue

支持两个附加操作的 Queue,这两个操作是:获取元素时等待队列变为非空,以及存储元素时等待空间变得可用.

BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(nullfalse,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞.下表中总结了这些方法:

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

改写之前的消费者生产者模式

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; class Product{
int id;
Product(int id){
this.id=id;
}
@Override
public String toString() {
return super.toString();
}
}
class Productor implements Runnable{
BlockingQueue<Product> blockingQueue = null;
public Productor(BlockingQueue<Product> blockingQueue ) {
this.blockingQueue=blockingQueue;
}
@Override
public void run() {
for(int i=;i<;i++){
Product p =new Product(i);
try {
blockingQueue.put(p);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"生成了一个"+p);
}
}
}
class Comsumer implements Runnable{
BlockingQueue<Product> blockingQueue = null;
public Comsumer(BlockingQueue<Product> blockingQueue ) {
this.blockingQueue=blockingQueue;
}
@Override
public void run() {
Product p=null;
for(;;){
try {
p = blockingQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"消费了一个"+p);
}
}
} public class TestBlockingQueue {
public static void main(String[] args) {
BlockingQueue<Product> b = new LinkedBlockingQueue<Product>();
Productor p = new Productor(b);
Comsumer c = new Comsumer(b);
new Thread(p).start();
new Thread(p).start();
new Thread(c).start();
new Thread(c).start();
}
}

四、ArrayBlockingQueue

一个由数组支持的有界阻塞队列,构造方法必须定义确定大小的队列,此队列按 FIFO(先进先出)原则对元素进行排序.队列的头部 是在队列中存在时间最长的元素.队列的尾部 是在队列中存在时间最短的元素.新元素插入到队列的尾部,队列获取操作则是从队列头部开始获得元素.

这是一个典型的“有界缓存区”,固定大小的数组在其中保持生产者插入的元素和使用者提取的元素.一旦创建了这样的缓存区,就不能再增加其容量.试图向已满队列中放入元素会导致操作受阻塞;试图从空队列中提取元素将导致类似阻塞.

ArrayBlockingQueue中的方法基本都使用了同步,例生产者消费者的底层代码:

final Object[] items;
final ReentrantLock lock;
private final Condition notEmpty;
private final Condition notFull;
public ArrayBlockingQueue(int capacity, boolean fair) {
if (capacity <= 0)
throw new IllegalArgumentException();
this.items = new Object[capacity];
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
}
private void enqueue(E x) {
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();
}
private E dequeue() {
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();
return x;
}
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}

五、LinkedBlockingQueue

一个基于已链接节点的、范围任意的 blocking queue.此队列按 FIFO(先进先出)排序元素.队列的头部 是在队列中时间最长的元素.队列的尾部 是在队列中时间最短的元素.新元素插入到队列的尾部,并且队列获取操作会获得位于队列头部的元素.链接队列的吞吐量通常要高于基于数组的队列,但是在大多数并发应用程序中,其可预知的性能要低.

可选的容量范围构造方法参数作为防止队列过度扩展的一种方法.如果未指定容量,则它等于 Integer.MAX_VALUE.除非插入节点会使队列超出容量,否则每次插入后会动态地创建链接节点.例其中一个方法:

static class Node<E> {
E item;
Node<E> next;
Node(E x) { item = x; }
}
private void enqueue(Node<E> node) {
last = last.next = node;
}
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
notFull.await();
}
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}

PriorityQueue一个基于优先级无界优先级队列.优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的Comparator进行排序,具体取决于所使用的构造方法.

PriorityBlockingQueue一个无界阻塞队列,它使用与类 PriorityQueue 相同的顺序规则,并且提供了阻塞获取操作.

LinkedBlockingDeque一个基于已链接节点的、任选范围的阻塞双端队列

SynchronousQueue每个插入操作必须等待另一个线程的对应移除操作.

DelayQueue个无界阻塞队列,只有在延迟期满时才能从中提取元素.

注:1.以上所有队列都不能插入null元素,因为很多方法的返回值是null.

2.队列与List接口不同,此接口不支持通过索引访问元素.队列只能从头部和尾部获取元素.

javase(12)_集合框架_Queue的更多相关文章

  1. javase(8)_集合框架_List、Set、Map

    一.集合体系(不包括Queue体系) 二.ArrayList ArrayList的属性 private transient Object[] elementData; //存储元素 private i ...

  2. JavaSE中Collection集合框架学习笔记(2)——拒绝重复内容的Set和支持队列操作的Queue

    前言:俗话说“金三银四铜五”,不知道我要在这段时间找工作会不会很艰难.不管了,工作三年之后就当给自己放个暑假. 面试当中Collection(集合)是基础重点.我在网上看了几篇讲Collection的 ...

  3. JavaSE中Collection集合框架学习笔记(3)——遍历对象的Iterator和收集对象后的排序

    前言:暑期应该开始了,因为小区对面的小学这两天早上都没有像以往那样一到七八点钟就人声喧闹.车水马龙. 前两篇文章介绍了Collection框架的主要接口和常用类,例如List.Set.Queue,和A ...

  4. JavaSE学习总结第15天_集合框架1

      15.01 对象数组的概述和使用 public class Student { // 成员变量 private String name; private int age; // 构造方法 publ ...

  5. JavaSE学习总结第18天_集合框架4

      18.01 Map集合概述和特点 Map接口概述:将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值 Map接口和Collection接口的不同 1.Map是双列的,Coll ...

  6. Java之旅_高级教_集合框架

    摘自:http://www.runoob.com/java/java-collections.html Java 集合框架 早在Java2之前,java 就提供了特设类.比如:Dictionary,V ...

  7. JavaSE复习_9 集合框架复习

    △列表迭代器也是不支持在迭代的时候添加元素的,只是列表迭代器自己定义了增删的方法而已.迭代器可以看成实在两个元素之间的指针,每当调用next就跳过一个元素并返回刚刚跳过的元素. △HashTable不 ...

  8. java oop第07章_集合框架

    一. 什么是集合: 在Java中提供了一些可以保存同一数据类型的数据集称为集合,就是规定了一些集合的规范(接口.抽象类.实现类)及方法, 方便我们程序在保存数据时进行增.删.改.查操作,编程更加高效. ...

  9. JavaSE学习总结第16天_集合框架2

      16.01 ArrayList存储字符串并遍历 ArrayList类概述:底层数据结构是数组,查询快,增删慢,线程不安全,效率高 ArrayList类是List 接口的大小可变数组的实现.实现了所 ...

随机推荐

  1. Java并发编程,互斥同步和线程之间的协作

    互斥同步和线程之间的协作 互斥同步 Java 提供了两种锁机制来控制多个线程对共享资源的互斥访问,第一个是 JVM 实现的 synchronized,而另一个是 JDK 实现的 ReentrantLo ...

  2. Sublime Text 报“Pylinter could not automatically determined the path to lint.py

    Pylinter could not automatically determined the path to lint.py. please provide one in the settings ...

  3. luoguP3808[模板]AC自动机(简单版)

    传送门 ac自动机模板题,裸的多串匹配 代码: #include<cstdio> #include<iostream> #include<algorithm> #i ...

  4. MySQL习题1 一对多实例 产品和分类

    /* 需求:建立产品和分类表 1.查询每种分类的产品数量,没有产品的分类也要统计.(cname,quantity) 2.根据分类名称查询分类中的所有产品 */ -- ----------------- ...

  5. C - How Many Tables

    #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> ...

  6. vs 对网站和项目使用IIS Express 的64位版

  7. mongodb-Configuration

    命令行和配制后文件接口为Mongodb的管理者提供了大量的控制选项.在这篇文章中提供了对于一般应用场景的最佳实践配置. mongod --config /etc/mongod.conf mongod ...

  8. UWP 保存用户设置

    一:需求 需要保存用户设置,用户下一次再打开app时,加载默认的设置.比如用户设置的主题颜色,用户自定义的文件保存路径等. 一般应用的的数据存储分为两种,一种是云存储(将数据保存在云端,下次打开的时候 ...

  9. STM32的低功耗模式

    一 待机模式standby和STOP模式的区别: 进入低功耗模式:都一样,都是先关闭相应时钟,关闭相应外设,配置相应所有IO口(浮动输入),然后配置相应的唤醒中断源,中断影响的O口,然后调用相应函数进 ...

  10. ZOJ How Many Nines 模拟 | 打表

    How Many Nines Time Limit: 1 Second      Memory Limit: 65536 KB If we represent a date in the format ...