ArrayBlockingQueue浅析

BlockingQueue是java的一个线程安全的阻塞队列的接口,

ArrayBlockingQueue 实现了 此接口,很简单,从名字上可以看出来,内部是 数组 实现的

ArrayBlockingQueue 源码中的部分变量:

    final Object[] items;  //存储所有元素的地方
    int takeIndex;  //获取元素的时候就是取出  takeIndex位置的元素
    int putIndex;  //添加元素根据 putIndex添加到指定位置
    int count;  //队列中的元素个数
    final ReentrantLock lock; 

   /**    ArrayBlockingQueue就是通过notEmpty和 notFull来实现阻塞功能的 */
    private final Condition notEmpty;  
    private final Condition notFull;
    transient Itrs itrs = null;    //暂时不知道用来干嘛的


offer方法,用于往队列里面添加元素,

public boolean offer(E e) {
        checkNotNull(e);     //判断是否为null
        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) {
        final Object[] items = this.items;
        items[putIndex] = x;     //元素x放入 putIndex的位置
        if (++putIndex == items.length)       //先putIndex加一,再判断putIndex到达末尾,再从0开始
            putIndex = 0;
        count++;
        notEmpty.signal();  //通知 正在 notEmpty上等待的线程, 
    }

put方法,若元素已满会一直等待

public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();  
        try {
            while (count == items.length)
                notFull.await();  //等待,直到dequeue方法获取元素后调用notFull.signal()
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }

take方法,从队列获取元素,若没有,则等待

public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)   
                notEmpty.await();  //没有元素就等待
            return dequeue();  //出队
        } finally {
            lock.unlock();
        }
    }


dequeue方法

  private E dequeue() {
        final Object[] items = this.items;
        E x = (E) items[takeIndex];  //获取takIndex位置的元素
        items[takeIndex] = null;  //将takeIndex的元素设置为null
        if (++takeIndex == items.length)  //先takeIndex加一,在判断是否等于数组长度
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        notFull.signal();  //唤醒正在等待 notFull的线程
        return x;
    }

ArrayBlockingQueue的方法不多,基本就2大类

一类是  获取元素,如 poll,, take,peek

一类是 添加元素,如 add ,offer,put


然后各自实现了不同的特性, 如  获取(取出)不到是 继续等待,还是返回false 还是抛出异常等

内部用 ReentrantLock 实现同步,

当添加元素时,通过 notFull阻塞,  直到 等待 dequeue方法调用,唤醒notFull的线程

同理, 当获取元素时, 通过 notEmpty阻塞,  等待  enqueue方法调用,唤醒notEmpty的线程

简单且实用

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值