认识ArrayBlockingQueue

最近想学习JUC的内容,就先攻克一下队列吧,平时自己用queue的场景较少,倒是了解过有很多东西是基于queue的,比如消息中间件啊。还是从常用的一些方法入手。

1.构造函数:ArrayBlockingQueue (int capacity)

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();//非空condition
        notFull =  lock.newCondition();//非满condition
}

2.add(E e)增加一个元索 。如果队列已满,则抛出一个IIIegaISlabEepeplian异常

public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
}
//添加一个元素并返回true       如果队列已满,则返回false
public boolean offer(E e) {
        checkNotNull(e);//检查e是否为null
        //保证线程安全,同步
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            //判断数组容量是否已满
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
}
private void enqueue(E x) {
        final Object[] items = this.items;
        items[putIndex] = x;
        //如果数组容量满了,那么 putIndex(下一次放入的位置)设置为0
        //记录下次放进去的位置,是从头到尾:有点类似与指针一样
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();//非空  线程唤醒
}

3.remove() 移除并返回队列头部的元素。如果队列为空,则抛出一个NoSuchElementException异常

public E remove() {
        E x = poll();
        if (x != null)
            return x;
        else
            throw new NoSuchElementException();
}
//移除并返问队列头部的元素    如果队列为空,则返回null
public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : dequeue();
        } finally {
            lock.unlock();
        }
}
private E dequeue() {
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        //记录下次拿出来的位置
        if (++takeIndex == items.length)
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        notFull.signal();//非满 线程唤醒
        return x;
}

4.peek()  返回队列头部的元素。如果队列为空,则返回null

public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            //takeIndex是 下一个应该被拿出来的下标
            return itemAt(takeIndex); // null when queue is empty
        } finally {
            lock.unlock();
        }
}
final E itemAt(int i) {
        return (E) items[i];
}
5.put(E e) 添加一个元素。如果队列满,则阻塞
public void put(E e) throws InterruptedException {
        //检查e是否为null
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();//可中断地获取锁
        try {
            while (count == items.length)
                notFull.await();//当前线程等待
            enqueue(e);
        } finally {
            lock.unlock();
        }
}

6.take() 移除并返回队列头部的元素 ,如果队列为空,会阻塞

public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();//可中断地获取锁
        try {
            while (count == 0)
                notEmpty.await();//当前线程挂起
            return dequeue();
        } finally {
            lock.unlock();
        }
}



猜你喜欢

转载自blog.csdn.net/qq_40384690/article/details/80726039