java并发相关

java阻塞队列 ArrayBlockingQueue

2018-09-10  本文已影响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 不能被中断返回。

上一篇下一篇

猜你喜欢

热点阅读