ArrayBlockingQueue知识点

JDK1.8版本,整理有关ArrayBlockingQueue的知识点,并对其中主要的方法进行分析

特点

1.有界队列(基于数组实现的)

2.先进先出

3.如果队列满了,put操作会阻塞;如果队列空了,take操作会阻塞。

4.支持公平或者非公平的策略(因为内部是使用ReentrantLock来实现阻塞的),公平策略(降低吞吐量)

5.使用经典的双条件算法来保证阻塞功能

6.写数据和消费数据使用同一把锁(这就导致写数据和消费数据并不能真正的并发)

主要方法

1.add(),offer(),put()方法

三者都是插入方法,add()时如果队列满了,会抛出异常;offer()如果队列满了,返回false;put方法,如果队列满了,阻塞等待

add()方法:
public boolean add(E e) {
        return super.add(e);//调用父类的add(),父类中又调用了offer()方法,所以最终还是调用offer()方法
    }
offer()方法
public boolean offer(E e) {
        checkNotNull(e); //判断元素是否为空
        final ReentrantLock lock = this.lock;
        lock.lock();//获取锁
        try {
            if (count == items.length) //判断队列是否已满,如果满了 直接返回 false
                return false;
            else {
                enqueue(e); //放入队列中
                return true;
            }
        } finally {
            lock.unlock(); //释放锁
        }
    }
put()方法
 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(); // 释放锁
        }
    }
	

2.poll(),take(),peek()方法

三者都是元素出队方法
1.peek()取出元素,但不会删除元素
2.poll()取出元素,并删除元素
3.take()取出元素,并且删除,如果队列为空的话,阻塞当前操作

1.peek()方法
 public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock(); //获取锁
        try {
            return itemAt(takeIndex); // 获取元素
        } finally {
            lock.unlock(); //释放锁
        }
    }
2.poll()
public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();//获取锁
        try {
            return (count == 0) ? null : dequeue(); //获取元素,并且删除元素
        } finally {
            lock.unlock();//释放锁
        }
    }
3.take()
 public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();//获取锁
        try {
            while (count == 0) //队列为空阻塞
                notEmpty.await();
            return dequeue(); //获取元素,并删除
        } finally {
            lock.unlock(); //释放锁
        }
    }

3.remove()方法

remove()移除元素,使用循环的方式移除

1.remove()方法
public boolean remove(Object o) {
        if (o == null) return false; //这个地方为什么不能直接抛异常
        final Object[] items = this.items;
        final ReentrantLock lock = this.lock; 
        lock.lock();//获取锁
        try {
            if (count > 0) {
                final int putIndex = this.putIndex;
                int i = takeIndex;
                do { //循环,直到找到要删除的元素
                    if (o.equals(items[i])) {
                        removeAt(i);
                        return true;
                    }
                    if (++i == items.length)
                        i = 0;
                } while (i != putIndex);
            }
            return false;
        } finally {
            lock.unlock(); //释放锁
        }
    }

本篇文章遗留的问题

1.Condition中的await() 和 signal()的方法

2.该阻塞队列使用的场景

转载于:https://my.oschina.net/nixi0608/blog/3083843

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值