`

集合框架 Queue篇(5)---ArrayBlockingQueue

 
阅读更多
Queue

------------
1.ArrayDeque, (数组双端队列)
2.PriorityQueue, (优先级队列)
3.ConcurrentLinkedQueue, (基于链表的并发队列)

4.DelayQueue,                                         (延期阻塞队列)(阻塞队列实现了BlockingQueue接口)
5.ArrayBlockingQueue,           (基于数组的并发阻塞队列)
6.LinkedBlockingQueue,        (基于链表的FIFO阻塞队列)
7.LinkedBlockingDeque, (基于链表的FIFO双端阻塞队列)
8.PriorityBlockingQueue,        (带优先级的无界阻塞队列)
9.SynchronousQueue                       (并发同步阻塞队列)
-----------------------------------------------------
ArrayBlockingQueue
是一个由数组支持的有界阻塞队列。此队列按 FIFO(先进先出)原则对元素进行排序。队列的头部 是在队列中存在时间最长的元素。队列的尾部 是在队列中存在时间最短的元素。新元素插入到队列的尾部,队列获取操作则是从队列头部开始获得元素。

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

此类支持对等待的生产者线程和消费者线程进行排序的可选公平策略。默认情况下,不保证是这种排序。然而,通过将公平性 (fairness) 设置为 true 而构造的队列允许按照 FIFO 顺序访问线程。公平性通常会降低吞吐量,但也减少了可变性和避免了“不平衡性”。

public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable {
    /** 队列元素 数组 */
    private final E[] items;

    /** 获取、删除元素时的索引(take, poll 或 remove操作) */
    private int takeIndex;
    /** 添加元素时的索引(put, offer或 add操作) */
    private int putIndex;

    /** 队列元素的数目*/
    private int count;


    /** 锁 */
    private final ReentrantLock lock;
    /** 获取操作时的条件 */
    private final Condition notEmpty;
    /** 插入操作时的条件 */
    private final Condition notFull;

    //超出数组长度时,重设为0
    final int inc(int i) {
        return (++i == items.length)? 0 : i;
    }

    /**
     * 插入元素(在获得锁的情况下才调用)
     */
    private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();
    }

    /**
     * 获取并移除元素(在获得锁的情况下才调用)
     */
    private E extract() {
        final E[] items = this.items;
        E x = items[takeIndex];
        items[takeIndex] = null;
        takeIndex = inc(takeIndex);//移到下一个位置
        --count;
        notFull.signal();
        return x;
    }

    /**
     * 删除i位置的元素
     */
    void removeAt(int i) {
        final E[] items = this.items;
        // if removing front item, just advance
        if (i == takeIndex) {
            items[takeIndex] = null;
            takeIndex = inc(takeIndex);
        } else {
            // 把i后面的直到putIndex的元素都向前移动一个位置
            for (;;) {
                int nexti = inc(i);
                if (nexti != putIndex) {
                    items[i] = items[nexti];
                    i = nexti;
                } else {
                    items[i] = null;
                    putIndex = i;
                    break;
                }
            }
        }
        --count;
        notFull.signal();
    }

    /**
     *构造方法,指定容量,默认策略(不是按照FIFO的顺序访问)
     */
    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }

    /**
     *构造方法,指定容量及策略
     */
    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = (E[]) new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }

    /**
     * 通过集合构造
     */
    public ArrayBlockingQueue(int capacity, boolean fair,
                              Collection<? extends E> c) {
        this(capacity, fair);
        if (capacity < c.size())
            throw new IllegalArgumentException();

        for (Iterator<? extends E> it = c.iterator(); it.hasNext();)
            add(it.next());
    }

    /**
     * 插入元素到队尾(super调用offer方法)
     *  public boolean add(E e) {
     *    if (offer(e))
     *        return true;
     *    else
     *       throw new IllegalStateException("Queue full");
     *  }
     * 将指定的元素插入到此队列的尾部(如果立即可行且不会超过该队列的容量),
     * 在成功时返回 true,如果此队列已满,则抛出 IllegalStateException。
     */
    public boolean add(E e) {
 return super.add(e);
    }

    /**
     * 将指定的元素插入到此队列的尾部(如果立即可行且不会超过该队列的容量),
     * 在成功时返回 true,如果此队列已满,则返回 false。
     */
    public boolean offer(E e) {
        if (e == null) throw new NullPointerException();
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                insert(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

    /**
     * 将指定的元素插入此队列的尾部,如果该队列已满,则等待可用的空间。
     */
    public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        final E[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            try {
                while (count == items.length)
                    notFull.await();
            } catch (InterruptedException ie) {
                notFull.signal(); // propagate to non-interrupted thread
                throw ie;
            }
            insert(e);
        } finally {
            lock.unlock();
        }
    }

    /**
     * 将指定的元素插入此队列的尾部,如果该队列已满,则在到达指定的等待时间之前等待可用的空间。
     */
    public boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException {

        if (e == null) throw new NullPointerException();
 long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            for (;;) {
                if (count != items.length) {
                    insert(e);
                    return true;
                }
                if (nanos <= 0)//如果时间到了就返回
                    return false;
                try {
                    nanos = notFull.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    notFull.signal(); // propagate to non-interrupted thread
                    throw ie;
                }
            }
        } finally {
            lock.unlock();
        }
    }

    //获取并移除此队列的头,如果此队列为空,则返回 null。
    public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == 0)
                return null;
            E x = extract();
            return x;
        } finally {
            lock.unlock();
        }
    }

    //获取并移除此队列的头部,在元素变得可用之前一直等待(如果有必要)。
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            try {
                while (count == 0)
                    notEmpty.await();
            } catch (InterruptedException ie) {
                notEmpty.signal(); // propagate to non-interrupted thread
                throw ie;
            }
            E x = extract();
            return x;
        } finally {
            lock.unlock();
        }
    }

    //获取并移除此队列的头部,在指定的等待时间前等待可用的元素(如果有必要)。
    public E poll(long timeout, TimeUnit unit) throws InterruptedException {
 long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            for (;;) {
                if (count != 0) {
                    E x = extract();
                    return x;
                }
                if (nanos <= 0)
                    return null;
                try {
                    nanos = notEmpty.awaitNanos(nanos);
                } catch (InterruptedException ie) {
                    notEmpty.signal(); // propagate to non-interrupted thread
                    throw ie;
                }

            }
        } finally {
            lock.unlock();
        }
    }

    //获取但不移除此队列的头;如果此队列为空,则返回 null。
    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : items[takeIndex];
        } finally {
            lock.unlock();
        }
    }

    /**
     * 返回此队列中元素的数量。
     */
    public int size() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }

    /**
     *返回在无阻塞的理想情况下(不存在内存或资源约束)此队列能接受的其他元素数量。
     */
    public int remainingCapacity() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return items.length - count;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 从此队列中移除指定元素的单个实例(如果存在)。
     */
    public boolean remove(Object o) {
        if (o == null) return false;
        final E[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            int i = takeIndex;
            int k = 0;
            for (;;) {
                if (k++ >= count)
                    return false;
                if (o.equals(items[i])) {
                    removeAt(i);
                    return true;
                }
                i = inc(i);
            }

        } finally {
            lock.unlock();
        }
    }

    /**
     * 如果此队列包含指定的元素,则返回 true。
     */
    public boolean contains(Object o) {
        if (o == null) return false;
        final E[] items = this.items;
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            int i = takeIndex;
            int k = 0;
            while (k++ < count) {
                if (o.equals(items[i]))
                    return true;
                i = inc(i);
            }
            return false;
        } finally {
            lock.unlock();
        }
    }

……

}

------------------------------------------
分享到:
评论

相关推荐

    Implementation-of-Queue-in-Java

    Java集合框架提供了一个名为`java.util.Queue`的接口,它是`Collection`接口的子接口。这个接口定义了队列操作的基本方法,如`add(E e)`(入队)、`remove()`(出队)、`element()`(获取但不移除队头元素)等。 3...

    java集合详细解释

    这篇博文链接虽然没有提供具体的内容,但是我们可以基于Java集合框架的常见知识点进行深入的解释。 首先,我们来了解一下Java集合框架的基本层次结构。在Java中,集合框架主要分为两大类:接口和实现。接口定义了...

    【死磕Java集合】-集合源码分析.pdf

    Java集合框架提供了多种数据结构和算法来存储和操作数据,包括LinkedList、ArrayList、HashMap、TreeMap、HashSet、TreeSet、ArrayBlockingQueue、PriorityQueue等。每种数据结构都有其特点和使用场景,需要根据实际...

    java中集合容器的详细介绍

    集合框架的核心是各种接口和类,它们定义了不同的数据结构,如列表(List)、队列(Queue)、集(Set)和映射(Map)等。 首先,让我们详细讨论一下集(Set)的概念。在数学中,集是一个包含唯一元素的无序组合。Java集合框架...

    Using_Java_Queue.zip_java队列

    Java队列是Java集合框架中的一个关键组成部分,主要用于在多个线程之间同步数据传输或实现异步处理。队列遵循先进先出(FIFO)的原则,即最早添加到队列中的元素将首先被处理。本教程将深入探讨如何在Java中使用队列...

    30个Java经典的集合面试题!.zip

    在Java编程语言中,集合框架是面试中经常讨论的话题,因为它构成了处理对象数组的基础。面试官经常通过提问关于集合的问题来评估候选人的基础知识、问题解决能力和实践经验。以下是一些Java集合框架中的关键知识点,...

    java常用的几种集合.doc

    Java集合框架是Java编程语言中一个非常重要的组成部分,主要用于存储和操作对象的集合。在Java中,集合类主要位于`java.util.*`包下,它们提供了多种数据结构,包括Set、List、Map以及Queue,这些数据结构都有各自...

    java中queue接口的使用详解

    Java中的`Queue`接口是Java集合框架的一部分,它位于`java.util`包中,是`Collection`接口的子接口。`Queue`接口主要用于实现队列数据结构,它遵循先进先出(FIFO)的原则,即最先添加的元素会被最先移除。在Java中...

    java基础及中级面试题+jvm面试题+集合面试题

    Java是世界上最流行的编程...对于Java程序员来说,扎实的基础知识、深入的JVM理解以及对集合框架的熟练运用,都是成为优秀开发者的关键。在准备面试的过程中,不断实践和加深理解,将有助于在职场上取得更大的成功。

    Java数据结构(三)

    在Java中,我们可以使用多种方式来实现队列,包括使用集合框架中的Queue接口以及其具体实现类。 首先,Java的`java.util.Queue`接口定义了队列的主要操作,如`add()`用于入队,`remove()`或`poll()`用于出队,`peek...

    java.util包

    1. 集合框架:Java.util包是Java集合框架的基础,包括List、Set、Queue和Map等接口,以及ArrayList、LinkedList、HashSet、HashMap等实现类。这些集合类为存储和操作对象提供了灵活的方式。例如,ArrayList实现了...

    Java 队列 Queue 用法实例详解

    首先,`java.util.Queue`是Java集合框架的一部分,它是所有队列类型的父接口。Queue接口提供了多种方法用于操作队列,包括添加元素、移除元素以及检查队首元素等。 1. 添加元素: - `add(E e)`:将指定的元素添加...

    Android校招面试指南 2018最新版本

    - **Java集合框架**:这是Java编程中非常重要的一个部分,主要用于处理数据集合。 - **ArrayList**:一种动态数组实现的数据结构,适用于频繁查询场景。 - **LinkedList**:双链表实现的数据结构,适合频繁插入...

    android-mvc

    - `LinkedList`或`ArrayList`可以作为基础队列结构,但它们在并发环境中不是线程安全的,需配合`synchronized`关键字或`java.util.concurrent`包中的并发集合使用。 - `java.util.concurrent`包提供了`...

    [计算机软件及应用]Java高级程序设计实验指导.doc

    集合框架包括List、Set、Queue等接口以及ArrayList、LinkedList、HashSet、HashMap等实现类。实验内容可能涵盖以下知识点: 1. **List接口**:List接口代表一个有序的集合,允许有重复元素。ArrayList和LinkedList...

    java面试题合集

    - **Queue**: 如`ArrayDeque`、`LinkedBlockingQueue`等,用于存储FIFO(先进先出)的数据结构。 - **Map**: 如`HashMap`、`TreeMap`等,用于存储键值对。 **4. ArrayList与LinkedList的区别** - **数据结构**: -...

    jdk的数据结构分析1

    2. **List**:List接口是Java集合框架的一部分,代表一个有序的元素列表,允许有重复元素。ArrayList和LinkedList是List的两种常见实现: - **ArrayList**:基于动态数组实现,提供随机访问(通过索引)的能力,...

    java并发编程-超级大全整理

    - **Java Queue接口**:是Java集合框架的一部分,不允许插入`null`元素。 - **队列操作**:插入(add() / offer())、移除(remove() / poll())、检查(element() / peek())等。 - **JDK中的队列实现**:...

    Java Core及底层面试问题.pdf

    - Java集合框架提供了多种集合类型,如`List`、`Set`、`Map`等。 - 每种集合类型都有其特点和适用场景。 通过以上总结,我们可以看到Java不仅是一门语言,更是一个强大的工具集,涵盖了从面向对象设计、多线程...

    java数据结构代码

    5. **集合**:Java集合框架包括List、Set和Queue接口,以及ArrayList、LinkedList、HashSet、TreeSet、ArrayBlockingQueue等具体实现。集合框架允许动态存储和操作对象,提供了丰富的操作方法。 6. **映射(Map)**...

Global site tag (gtag.js) - Google Analytics