ArrayBlockingQueue分析

ArrayBlockingQueue概述

  1. 这是一个由有限的数组、且支持阻塞的队列。 这个队列排列元素FIFO(先进先出), 新元素插入队列的尾部,队列检索操作获取队列头部的元素。
  2. 这是一个经典的“有界缓冲区”,其中固定大小的数组保存由生产者插入的元素并由消费者提取。
  3. 创建后,容量无法更改。 当队列已满时,put操作会使队列阻塞; 而尝试take操作从空队列的队列也同样发类似地阻塞。
  4. 此类支持可选的公平策略,用于订阅和等待的生产者和消费者线程。 公平设置为true的队列以FIFO顺序授予线程访问权限。 公平性通常会降低吞吐量,但可以避免饥饿。
  5. 这个类是Java Collections Framework的成员,在Java1.5提供。

类结构

public class ArrayBlockingQueue<E>
	extends AbstractQueue<E>
	implements BlockingQueue<E>, Serializable

特征

  1. 内部数据结构: 它基于环形数组来存储元素。数组的第一个和最后一个元素在逻辑上相邻;每当从队列中添加/删除元素时,队列都会使头元素/尾元素的索引前进。当任一索引使数组中的最后一个元素前进时,它将从0重新开始。这种机制比使用常规数组更好,因为每当移除磁头时队列都不必移动所有元素。但如果您删除中间的一个元素(通过Iterator.remove),则它必须移动这些元素;
  2. 容量: ArrayBlockingQueue可以容纳的元素数量有限制,因为在构造此类的新对象时必须指定容量。因此,ArrayBlockingQueue是有界的BlockingQueue;
  3. 顺序: 由于它基于数组,因此元素按FIFO(先进先出)顺序排列;
  4. 操作: 队列插入和删除在固定时间内执行(非常快);
  5. Iterator: 由ArrayBlockingQueue 返回的迭代器是弱一致性的,这意味着该迭代器可以与其他操作并发使用。它永远不会抛出ConcurrentModificationException并支持remove操作。

成员属性

在这里插入图片描述

构造方法

ArrayBlockingQueue(int capacity) 
	创建具有给定(固定)容量和默认访问策略的 ArrayBlockingQueue 。  
ArrayBlockingQueue(int capacity, boolean fair) 
	创建一个 ArrayBlockingQueue具有给定(固定)容量和指定访问策略。  
ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) 
	创建一个 ArrayBlockingQueue具有给定(固定)容量,指定访问策略和最初包含给定集合中的元素,添加在收集迭代器的遍历顺序。  

常用方法

boolean add(E e) 
在插入此队列的尾部,如果不超过该队列的容量,则返回true功,如果此队列已满,抛出 IllegalStateExceptio。 
boolean offer(E e) 
如果可以在不超过队列容量的情况下立即将其指定的元素插入该队列的尾部,则在成功时 false如果该队列已满,则返回 trueboolean offer(E e, long timeout, TimeUnit unit) 
在该队列的尾部插入指定的元素,等待指定的等待时间,以使空间在队列已满时变为可用。 
void put(E e) 
在该队列的尾部插入指定的元素,如果队列已满,则阻塞。 

E peek() 
检索但不删除此队列的头,如果此队列为空,则返回 null 。  
E poll() 
检索并删除此队列的头,如果此队列为空,则返回 null 。  
E poll(long timeout, TimeUnit unit) 
检索并删除此队列的头,等待指定的等待时间(如有必要)使元素变为可用。  
E take() 
检索并删除此队列的头,如有必要,等待元素可用。  

void clear() 
从这个队列中原子地删除所有的元素。 
boolean remove(Object o) 
从该队列中删除指定元素的单个实例(如果存在)。  

boolean contains(Object o) 
如果此队列包含指定的元素,则返回 true 。  

Iterator<E> iterator() 
以适当的顺序返回该队列中的元素的迭代器。  
Spliterator<E> spliterator() 
返回此队列中的元素Spliterator 。  

Object[] toArray() 
以适当的顺序返回一个包含此队列中所有元素的数组。  
<T> T[] toArray(T[] a) 
以适当的顺序返回包含此队列中所有元素的数组; 返回的数组的运行时类型是指定数组的运行时类型。 

重要方法解读分析

  1. ArrayBlockingQueue(int capacity, boolean fair) 构造方法
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();
    }
  1. put(E e)阻塞新增方法
 public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();//表示队列已满,将线程挂起,并由notFull实例监听
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }
    /**
     * Inserts element at current put position, advances, and signals.
     * Call only when holding lock.
     */
     private void enqueue(E x) {
        // assert lock.getHoldCount() == 1;
        // assert items[putIndex] == null;
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();//唤醒等待队列进行take操作的线程
    }
  1. E take()
 public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();//表示队列为空,需要将线程挂起
            return dequeue();
        } finally {
            lock.unlock();
        }
    }
    
 	/**
     * Extracts element at current take position, advances, and signals.
     * Call only when holding lock.
     */
    private E dequeue() {
        // assert lock.getHoldCount() == 1;
        // assert items[takeIndex] != null;
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E x = (E) items[takeIndex];
        items[takeIndex] = null;//删除元素
        if (++takeIndex == items.length)
            takeIndex = 0;//表示已从队列中的获取最后一个元素,下次获取需从索引0开始
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        notFull.signal();//唤醒等待put操作的线程
        return x;
    }
    
	void elementDequeued() {
            // assert lock.getHoldCount() == 1;
            if (count == 0)
                queueIsEmpty();//当队列为空时,通知所有迭代器,并且清除所有弱引用
            else if (takeIndex == 0)
                takeIndexWrapped();//通知所有迭代器,并删除所有过时的迭代器
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值