Java 并发容器 -- BlockingQueue

BlockingQueue接口

Queue

常用方法

Throws exception Returns special value
Insert add offer
Remove remove poll
Examine element peek

Queue接口

package java.util

public interface Queue<E> extends Collection<E> {
    // 向队列尾部插入一个无素,如果是有界队列,此时队列已满,则抛出IllegalStateException异常
    boolean add(E e);
    // 同add方法的区别是:如果是有界队列,此时队列已满,则返回false
    boolean offer(E e);
    // 从队列的头部取出一个元素并删除该无素。如果队列是空,则抛出NoSuchElementException异常
    E remove();
    // 同remove方法的区别是:如果队列是空,则返回null
    E poll();
    // 从队列的头部获取一个元素但不删除该元素,如果队列是空,则抛出NoSuchElementException异常
    E element();
    // 同element方法的区别是:如果队列是空,则返回null
    E peek();
}

Deque

常用方法

  • First element (Head)
  • Last element (Tail)
Throws Exception Returns special value Throws Exception Returns special value
Insert addFirst offerFirst addLast offerLast
Remove removeFirst pollFirst removeLast pollLast
Examine getFirst peekFirst getLast peekLast

Deque与Queue

Queue和Deque的一些方法的功能是一样的。如下表:

Queue Method Equivalent Deque Method
add addLast
offer offerLast
remove removeFirst
poll pollFirst
element getFirst
peek peekFirst

Deque与Stack

Deque可以作为LIFO(Last-In-First-Out),和Stack一样。

Stack Method Equivalent Deque Method
push addFirst
pop removeFirst
peek peekFirst

Deque接口

public interface Deque<E> extends Queue<E> {
    // 向队列的头部插入一个元素。如果是有界队列,此时队列已满,则抛出IllegalStateException异常
    void addFirst(E e);
    // 向队列的尾部插入一个元素。如果是有界队列,此时队列已满,则抛出IllegalStateException异常
    void addLast(E e);
    // 向队列的头部插入一个元素。如果是有界队列,此时队列已满,则返回false
    boolean offerFirst(E e);
    // 向队列的尾部插入一个元素。如果是有界队列,此时队列已满,则返回false
    boolean offerLast(E e);
    // 从队列的头部取出一个元素并删除该无素。如果队列是空,则抛出NoSuchElementException异常
    E removeFirst();
    // 从队列的尾部取出一个元素并删除该无素。如果队列是空,则抛出NoSuchElementException异常
    E removeLast();
    // 从队列的头部取出一个元素并删除该无素。如果队列是空,则返回null
    E pollFirst();
    // 从队列的尾部取出一个元素并删除该无素。如果队列是空,则返回null
    E pollLast();
    // 从队列的头部获取一个元素但不删除该元素,如果队列是空,则抛出NoSuchElementException异常
    E getFirst();
    // 从队列的尾部获取一个元素但不删除该元素,如果队列是空,则抛出NoSuchElementException异常
    E getLast();
    // 从队列的头部获取一个元素但不删除该元素,如果队列是空,则返回null
    E peekFirst();
    // 从队列的尾部获取一个元素但不删除该元素,如果队列是空,则返回null
    E peekLast();
    // 删除队列第一次出现该元素。如果不存在则返回false
    boolean removeFirstOccurrence(Object o);
    // 删除队列最后一次出现该元素,如果不存在则返回false
    boolean removeLastOccurrence(Object o);

    // *** Queue methods ***
    
    // 同 addLast 方法一样
    boolean add(E e);
    // 同 offerLast 方法一样
    boolean offer(E e);
    // 同 removeFirst 方法一样
    E remove();
    // 同 pollFirst 方法一样
    E poll();
    // 同 getFirst 方法一样
    E element();
    // 同 peekFirst 方法一样
    E peek();


    // *** Stack methods ***
    
    // 同 addFirst 方法一样
    void push(E e);
    // 同 removeFirst 方法一样
    E pop();

    // *** Collection methods ***

    // 同 removeFirstOccurrence 方法一样
    boolean remove(Object o);
    // 队列中包含指定的元素时返回true(至少有一个), 否则返回false
    boolean contains(Object o);
    // 队列中的元素个数
    public int size();
    // 提供从 head -> tail 方式遍历队列元素
    Iterator<E> iterator();
    // 提供从 tail -> head 方法遍历队列元素
    Iterator<E> descendingIterator();

}

BlockingQueue

BlockingQueue是线程安全的阻塞队列。通常用于实现生产者-消费者的情形。

BlockingQueue新增支持阻塞的相关方法:

  • 当队列已满时:则不允许插入元素,此时方法处于阻塞状态,直到队列不为空时,才可以继续执行。
  • 当队队列为空时:则不允拿走元素,此时方法处于阻塞状态,直到队列中有元素时,才可以继续执行。

常用方法

Throws exception Returns special value Blocks Times out
Insert add offer put offer(long, TimeUnit)
Remove remove poll take poll(long, TimeUnit)
Examine element peek -- --

BlockingQueue接口

public interface BlockingQueue<E> extends Queue<E> {
    // 向队列尾部插入一个无素,如果是有界队列,此时队列已满,则抛出IllegalStateException异常
    boolean add(E e);
    // 向队列尾部插入一个无素,如果是有界队列,此时队列已满,则返回false
    boolean offer(E e);
    // 向队列尾部插入一个无素,如果是有界队列,此时队列已满,则调用此方法的线程处于阻塞状态。注意该方法支持被设置中断
    void put(E e) throws InterruptedException;
    // 向队列尾部插入一个无素,如果是有界队列,此时队列已满,则调用此方法的线程在指定的时间内处于阻塞状态。如果指定时间内不能插入元素则返回false。注意该方法支持被设置中断
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;
    // 从队列的头部取出一个元素并删除该无素。如果队列是空,则调用些方法的线程处于阻塞状态。注意该方法支持被设置中断。
    E take() throws InterruptedException;
    // 从队列的头部取出一个元素并删除该元素,如果队列是空,则调用此方法的线程在指定的时间内处于阻塞状态。如果指定时间内不能获取到元素,则返回null。注意该方法支持被设置中断
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;
    // 返回队列中剩余的容量。注意,不能用该方法来判断队列是否已满或已空来决定是否插入或拿走操作。
    int remainingCapacity();
    // 从队列中删除指定的元素,如果不存在则返回false
    boolean remove(Object o);
    // 指定元素是否存在队列中
    public boolean contains(Object o);
    // 删除队列中所有元素并添加到Collection集合中。此方法比重复执行poll方法要更高效。
    int drainTo(Collection<? super E> c);
    // 删除队列中指定元素个数并添加到Collection集合中
    int drainTo(Collection<? super E> c, int maxElements);
}

TransferQueue

TransferQueue提供生产者可以等待(阻塞)消费者收到消息的相关功能。如生产者线程调用transfer方法时,必须等到消费者线程调用take方法或poll方法拿到消息时,生产者线程才可以继续往下处理,否则一直处于阻塞状态。

TransferQueue接口

public interface TransferQueue<E> extends BlockingQueue<E> {
    // 生产者线程尝试传输消息,如果有消费者线程调用take或poll方法时,该方法返回true,否则返回false。Non-blocking
    boolean tryTransfer(E e);
    // 生产者传输消息,如果有消费者线程调用take或poll方法,该方法直接返回;否则该线程处于阻塞状态
    void transfer(E e) throws InterruptedException;
    // 生产者线程在指定的时间内尝试传输消息,如果有消费者线程调用take或poll方法时,该方法返回true,如果超出指定时间内则返回false
    boolean tryTransfer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;
    // 是否存在有等待获取消息的消费者
    boolean hasWaitingConsumer();
    // 正在等待获取消息的消费者的数量
    int getWaitingConsumerCount();
}

AbstractQueue

AbstractQueue是抽象类实现了部分Queue的方法,如add、remove、element方法;继承了AbstractCollection类,实现了clear、addAll方法。

AbstractQueue抽象类采用模板方法的设计模式.

public abstract class AbstractQueue<E>
    extends AbstractCollection<E>
    implements Queue<E> {
    
    protected AbstractQueue() {
    }
    
    public boolean add(E e) {
        // offer方法由子类实现,如果offer方法返回false,则抛IllegalStateException异常
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }

    public E remove() {
        // poll方法由子类实现,如果poll方法返回null,则抛NoSuchElementException异常
        E x = poll();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }

    public E element() {
        // peek方法由子类实现,如果peek方法返回null,则抛NoSuchElementException异常
        E x = peek();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }

    public void clear() {
        // 轮徇调用poll方法删除队列中的元素
        while (poll() != null)
            ;
    }
}

小结

总结Queue、Deque、BlockingQueue和TransferQueue接口相关的方法的说明。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。