On ArrayBlockingQueue 1.8 source code

[TOC]

On ArrayBlockingQueue 1.8 source code

I. Introduction

ArrayBlockingQueue array is implemented with a bounded queue; this queue orders elements in accordance with the rules of FIFO (FIFO); it does not guarantee fair access to the queue threads by default, refers to the so-called fair access to the queue is blocked thread, in accordance with blocking access to the order of the queue, that is, first blocked thread to access the queue; non fairness on the thread to wait for non-fair, when the queue is available, the blocked thread can be eligible to compete for access to the queue, it is possible to clog thread finally access; in order to ensure fairness, generally decreases throughput.

Second, FIG UML class

On ArrayBlockingQueue 1.8 source code

Third, the basic member

    /** The queued items */
    // 记录数据的数组
    final Object[] items;

    /** items index for next take, poll, peek or remove */
    // 索引用于 take,poll,peek,remove 等方法
    int takeIndex;

    /** items index for next put, offer, or add */
    // 索引用于 put,offer,or add 等方法
    int putIndex;

    /** Number of elements in the queue */
    // 总数
    int count;

    /*
     * Concurrency control uses the classic two-condition algorithm
     * found in any textbook.
     */

    /** Main lock guarding all access */
    // 队列的锁
    final ReentrantLock lock;

    /** Condition for waiting takes */
    // 用于让线程等待,消费时队列为空
    private final Condition notEmpty;

    /** Condition for waiting puts */
    // 用于让线程等待,生产时队列满
    private final Condition notFull;

Fourth, the common method

Construction method

We look at two configurations, in fact, is a notice there are no constructor with no arguments, it must be given the capacity during initialization.

    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }

    // 初始化一个ArrayBlockingQueue
    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();
    }
add method

It can be seen that offer add call method, details offer methods.

    public boolean add(E e) {
        // 调用父类的方法
        return super.add(e);
    }

    // 父类 AbstractQueue 的add方法
     public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }

Note: add insert failure will throw an exception.

offer methods
    // offer加入元素
    public boolean offer(E e) {
        // 不能为null
        checkNotNull(e);
        // 获取锁
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            // 如果数组满了,返回false
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }
    // enqueue

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

Note: offer there is an overloaded method, with the insertion of the timeout, support interrupt offer (E e, long timeout, TimeUnit unit).

put method
public void put(E e) throws InterruptedException {
        // 不能为null
        checkNotNull(e);
        // 获取锁
        final ReentrantLock lock = this.lock;
        // 支持中断
        lock.lockInterruptibly();
        try {
            // 等于数组的容量
            while (count == items.length)
                // 等待
                notFull.await();
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }

Note: put in front of the offer and to distinguish between, offer full queue method returns false, put method is to let the thread to wait with the appropriate method according to their own scenes.

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

Note: poll also has an overloaded method, with a timeout and interrupts poll (long timeout, TimeUnit unit).

take way
    // 消费
    public E take() throws InterruptedException {
        // 获取锁
        final ReentrantLock lock = this.lock;
        // 支持中断
        lock.lockInterruptibly();
        try {
            // 队列为空
            while (count == 0)
                // 阻塞
                notEmpty.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

Note: take and poll also a method, return null poll queue is empty, take a thread to wait until awakened.

peek method
// 获取队尾的元素 不删除
    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return itemAt(takeIndex); // null when queue is empty
        } finally {
            lock.unlock();
        }
    }
size method
    // 统计个数 size是准确值
    public int size() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return count;
        } finally {
            lock.unlock();
        }
    }

V. Summary

ArrayBlockingQueue is bounded, so we have the capacity to design is good, because it is not expansion, and I think this queue for some stability in the amount of concurrent systems, if the amount of concurrency suddenly becomes large, resulting in the initialization queue is full, it will cause a lot of thread to wait response system; we also found that by reading the source queue source code is very lightweight, and very simple to use, people are well understood; using this queue must pay attention to put, offer, take, these two sets of poll method, according to their own business is a direct return to the scene selection (fast response) or blocked thread.

Reference: "Java concurrent programming art"

Guess you like

Origin blog.51cto.com/14220760/2411583