Java的arrayblockingqueue源码阅读

这个是我阅读源码时加了注释的源代码,直接贴上了一些我觉得比较有用的方法代码。有一些比较简单一看就懂的就没加注释

public class ArrayBlockingQueue<E> extends AbstractQueue<E>
        implements BlockingQueue<E>, java.io.Serializable {

    

    /** The queued items */
    //数组实现的队列
    final Object[] items;

    /** items index for next take, poll, peek or remove */
    //这个索引位置上的元素就是队列下一次移除的元素
    int takeIndex;

    /** items index for next 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 */
    //一个锁对象,这里用的时lock类而不是object原因我认为可能是object只有一个monitor而
    //而lock可以同时维护多个condition
    final ReentrantLock lock;

    /** Condition for waiting takes */
    //一个弹出操作时用到的判断是否为空的等待队列监听器
    private final Condition notEmpty;

    /** Condition for waiting puts */
    //判断是否满了的等待队列监听器
    private final Condition notFull;

    /**
     *
     *
     * 这里又看到这个类了,这个类之前在arraylist中做过详细的阅读,
     * 这里封装的应该是差不多的东西
     */
    transient Itrs itrs = null;

    // Internal helper methods
    //下面都是一些队列内部完成功能的方法类似于arraylist的<code>E element()<code>方法

    /**
     * Circularly decrement i.
     * 循环递减
     *
     */
    final int dec(int i) {
        return ((i == 0) ? items.length : i) - 1;
    }

    /**
     * Returns item at index i.
     * 返回指定索引的element
     */
    @SuppressWarnings("unchecked")
    final E itemAt(int i) {
        return (E) items[i];
    }

    /**
     * Throws NullPointerException if argument is null.
     *
     * @param v the element
     *
     * 检查这个object是否是null
     */
    private static void checkNotNull(Object v) {
        if (v == null)
            throw new NullPointerException();
    }

    /**
     * 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();//在弹出的等待队列中唤醒一个线程
    }

    /**
     * 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;//这里直接将index位置的设置为null
        if (++takeIndex == items.length)//这是判断当前索引位置是否到了数组末尾了
            takeIndex = 0;
        count--;//元素个数--
        if (itrs != null)//将
            itrs.elementDequeued();
        notFull.signal();//唤醒一个在压入的condition中的线程
        return x;
    }

    /**
     * Deletes item at array index removeIndex.
     * Utility for remove(Object) and iterator.remove.
     * Call only when holding lock.
     * 这个方法与上面那个弹出不同,他不会返回元素而是直接移除,通养要获取锁
     */
    void removeAt(final int removeIndex) {
        // assert lock.getHoldCount() == 1;
        // assert items[removeIndex] != null;
        // assert removeIndex >= 0 && removeIndex < items.length;
        final Object[] items = this.items;
        if (removeIndex == takeIndex) {
            // removing front item; just advance
            items[takeIndex] = null;
            if (++takeIndex == items.length)
                takeIndex = 0;
            count--;
            if (itrs != null)
                itrs.elementDequeued();
        } else {
            // an "interior" remove

            // slide over all others up through putIndex.
            final int putIndex = this.putIndex;
            for (int i = removeIndex;;) {
                int next = i + 1;
                if (next == items.length)
                    next = 0;
                if (next != putIndex) {
                    items[i] = items[next];
                    i = next;
                } else {
                    items[i] = null;
                    this.putIndex = i;
                    break;
                }
            }
            count--;
            if (itrs != null)
                itrs.removedAt(removeIndex);
        }
        notFull.signal();
    }

    
    /**
     * 
     * add方法依旧还是线程不安全的,来自于queue的方法
     */
    public boolean add(E e) {
        return super.add(e);
    }

    /**
     * 
     *
     * 如果可以*在不超过队列容量的情况下立即执行此操作,请在此队列的尾部插入指定的元素;
     * 成功返回{@code true},如果此队列已满则返回{@code false}。
     * 通常,此方法比方法{@link #add}
     * 更可取,后者只能通过引发异常而无法插入元素。
     *
     * 这个就是线程安全的压入方法了
     * @throws NullPointerException if the specified element is null
     */
    public boolean offer(E e) {
        checkNotNull(e);//先检查元素是否是null
        final ReentrantLock lock = this.lock;
        lock.lock();//尝试获取锁,获取失败的线程会进入同步队列
        try {//这里判断队列是否已满
            if (count == items.length)
                return false;//满了就直接停止压入并返回false
            else {
                enqueue(e);//没满就压入
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

    /**
     * 
     *
     * 将指定的元素插入此队列的末尾,如果队列已满,则等待空间变为可用。
     *
     * @throws InterruptedException {@inheritDoc}
     * @throws NullPointerException {@inheritDoc}
     */
    public void put(E e) throws InterruptedException {
        checkNotNull(e);//空检测
        final ReentrantLock lock = this.lock;//找到到锁的实例
        //这里使用的方法是会对interrupt状态进行检测的方法,如果是true就会抛出异常
        lock.lockInterruptibly();
        try {
            //看是否满了
            while (count == items.length)
                notFull.await();//满了就将当前线程放入等待队列,下次唤醒时从这里开始继续判断
            enqueue(e);//压入操作
        } finally {
            lock.unlock();
        }
    }

    /**
     * 
     *
     * 带超时属性的压入offer
     * @throws InterruptedException {@inheritDoc}
     * @throws NullPointerException {@inheritDoc}
     */
    public boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException {

        checkNotNull(e);
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length) {
                if (nanos <= 0)
                    return false;
                nanos = notFull.awaitNanos(nanos);
            }
            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();
        }
    }

    //弹出操作,为空进入等待队列
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return dequeue();
        } 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 {
            while (count == 0) {
                if (nanos <= 0)
                    return null;
                nanos = notEmpty.awaitNanos(nanos);
            }
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

    //这个方法将返回队列即将弹出的元素,但是不从数组中移除这个元素
    public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return itemAt(takeIndex); // null when queue is empty
        } finally {
            lock.unlock();
        }
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值