Collection 中 Queue 详解


在这里插入图片描述

ArrayBlockingQueue

1、定义

package java.util.concurrent;
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable {

2、简介
ArrayBlockingQueue 是一个基于数组的阻塞队列,创建时必须要指定数组的长度。
既然它在 J.U.C 包内,说明是支持并发线程安全的,内部使用 ReenTrantLock 来保证线程安全。

3、常用方法
offer、put 入队。
poll、take 出队。
offer 和 poll 非阻塞方法。
put 和 take 阻塞方法。

peek() 获取第一个入队的元素。
remove() 移除指定的元素。

3.1、入队方法
内部放入队列:

private void enqueue(E x)

add 方法,最终调用的是 offer 方法。

public boolean add(E e) {
    if (offer(e))
        return true;
    else
        throw new IllegalStateException("Queue full");
}

offer 方法,非阻塞方法,队列满时返回 false,否则调用 enqueue 放入队列,并返回 true。

public boolean offer(E e) {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        if (count == items.length)
            return false;
        else {
            enqueue(e);
            return true;
        }
    } finally {
        lock.unlock();
    }
}

put 方法,阻塞方法,队列满时,会一直等待,直到被其他线程唤醒,唤醒后调用 enqueue 放入队列。

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

3.2、出队方法
内部出队列:

private E dequeue()

poll 方法,非阻塞方法,队列没有元素返回 null,否则调用 dequeue 出队。

public E poll() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        return (count == 0) ? null : dequeue();
    } finally {
        lock.unlock();
    }
}

take 方法,阻塞方法,队列空时,会一直等待,直到被其他线程唤醒,唤醒后调用 dequeue 出队。

public E take() throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0)
            notEmpty.await();
        return dequeue();
    } finally {
        lock.unlock();
    }
}

总结:

ArrayBlockingQueue 是一个基于循环数组的阻塞型先进先出队列,内部有 ReentrantLock 实现线程安全,由 Condition 的 await 和 signal 实现等待唤醒功能。

LinkedBlockingQueue

和 ArrayBlockingQueue 有着同样的方法和性质,最大的不同是基于单向链表结构来保存数据的,是无界的。

LinkedBlockingDeque

是加强版的 LinkedBlockingQueue,内部维护一个双向链表来保存数据。
入队方法:
offer(E e)、offerFirst(E e)、offerLast(E e)
put(E e)、putFirst(E e)、putLast(E e)
出队方法:
poll()、pollFirst()、pollLast()
take()、takeFirst()、takeLast()

LinkedBlockingDeque 和 LinkedBlockingQueue 总结:

相同点:
基于链表;
容量可选,不设置的话,默认 int 最大值;

不同点:
LinkedBlockingDeque 是双向链表,LinkedBlockingQueue 是单向链表;
LinkedBlockingQueue 出队入队只能是先进先出;
LinkedBlockingDeque 可以任意选择队列头或队列尾进行出队入队。

ConcurrentLinkedQueue

非阻塞型的,使用CAS的方式来实现线程安全的,性能高于 ReentranLock。

Queue、Deque

实现 Deque 用的是双向链表。
实现 Queue 用的是单向链表。

LinkedList

定义:

package java.util;
public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

同时具有 List 和 Queue 功能,是一个双向链表结构,并发访问不是线程安全的。

参考:
http://benjaminwhx.com/categories/并发编程/

猜你喜欢

转载自blog.csdn.net/const_/article/details/89376734