美文网首页java并发相关
java阻塞队列 ArrayBlockingQueue

java阻塞队列 ArrayBlockingQueue

作者: 韭菜待收割 | 来源:发表于2018-09-10 16:03 被阅读6次
    package java.util.concurrent
    //由数组支持的有界队列
    public class ArrayBlockingQueue<E> extends AbstractQueue<E>
            implements BlockingQueue<E>, java.io.Serializable
    

    1、常用方法

    构造方法

    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }
    
    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();
    }
    
    public ArrayBlockingQueue(int capacity, boolean fair,
                              Collection<? extends E> c) {
        this(capacity, fair);
    
        final ReentrantLock lock = this.lock;
        lock.lock(); // Lock only for visibility, not mutual exclusion
        try {
            int i = 0;
            try {
                for (E e : c) {
                    checkNotNull(e);
                    items[i++] = e;
                }
            } catch (ArrayIndexOutOfBoundsException ex) {
                throw new IllegalArgumentException();
            }
            count = i;
            putIndex = (i == capacity) ? 0 : i;
        } finally {
            lock.unlock();
        }
    }
    

    父类AbstractQueue实现

    /**
     * 增加一个元索,如果队列已满,则抛出异常
     */
    public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }
    
    /**
     * 移除并返回队列头部的元素,如果队列为空,则抛出异常
     */
    public E remove() {
        E x = poll();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }
    
    /**
     * 返回队列头部的元素,如果队列为空,则抛出异常
     */
    public E element() {
        E x = peek();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
    }
    

    非阻塞方法

    /**
     * 添加一个元素并返回true,如果队列已满,则返回false
     */
    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();
        }
    }
    
    /**
     * 移除并返问队列头部的元素,如果队列为空,则返回null
     * */
    public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : dequeue();
        } finally {
            lock.unlock();
        }
    }
    
    /**
     * 返回队列头部的元素,如果队列为空,则返回null
     */
    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return itemAt(takeIndex); // null when queue is empty
        } finally {
            lock.unlock();
        }
    }    
    

    阻塞方法

    /**
     * 添加一个元素,如果队列满,则阻塞
     */
    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();
        }
    }   
    

    其它

    /**
     * 没有遍历整个队列
     */
    public int size() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }
    

    2、安全性如何保证?

    由ReentrantLock(可重入锁)提供。
    当队列添加元素后,会调用Condition notEmpty.signal();
    而put(E e)方法里会调用notFull.await(); 等待唤醒。

    当队列删除元素后,会调用Condition notFull.signal();
    而take()方法里会调用notEmpty.await(); 等待唤醒。

    3、三个构造方法里其中一个构造方法,构造指定初始化时加入一个集合,加锁的目的?

    加锁会保证其可见性,也就是写回主内存。

    4、源码中lock.lockInterruptibly();和lock.lock();有何区别?

    lockInterruptibly 可被线程中断返回,lock 不能被中断返回。

    相关文章

      网友评论

        本文标题:java阻塞队列 ArrayBlockingQueue

        本文链接:https://www.haomeiwen.com/subject/nzbsgftx.html