ArrayBlockingQueue原理(不介绍 WeakReference 弱引用)

ArrayBlockingQueue原理

ArrayBlockingQueue有一个定长数组用来存储存放的元素,并用一个属性count记
录存储元素的个数,每当调用take这样的方法是,ArrayBlockingQueue会根据自
己当前记录的takeIndex索引值,来获取对应索引处的元素,每当取到元素则
takeIndex++,计算下次take的索引位置,知道takeIndex = 数组长度,则将
takeIndex置为0.ArrayBlockingQueue的put方法也类似也有一个putIndex索引,从
索引0处开始放,方法putIndex等于数组长度时,则置为0.至于如何保证同步就是
使用ReentrantLock锁,与2个Condition来调度put 与take

在这里插入图片描述

API

public ArrayBlockingQueue(int capacity)
初始化ArrayBlockingQueue ---存储最大数目为capacity
public ArrayBlockingQueue(int capacity, boolean fair)
初始化ArrayBlockingQueue ---存储最大数目为capacity 公平/非公平可选
public boolean add(E e)
添加一个元素到ArrayBlockingQueue,添加失败抛异常
public void clear()
清空ArrayBlockingQueue中的元素
public boolean offer(E e)
添加一个元素到ArrayBlockingQueue
public E peek()
获取当前takeIndex处的元素
public E poll()
获取当前takeIndex处的元素,并删除该元素
public void put(E e) throws InterruptedException
阻塞的获取当前takeIndex处的元素,并删除该元素
public E take() throws InterruptedException
阻塞的添加一个元素到ArrayBlockingQueue,

源码分析

初始化

    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        存储数组    
        this.items = new Object[capacity];
        同步锁
        lock = new ReentrantLock(fair);
        调度Condition
        notEmpty = lock.newCondition();
        调度Condition
        notFull =  lock.newCondition();
    }
    
    成员属性
    /** 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;

add方法

  public boolean add(E e) {
      调用父类实现
      return super.add(e);
  }
   父类实现
   public boolean add(E e) {
     调用子类offer方法
     if (offer(e))
         return true;
     else  //添加失败则直接异常
         throw new IllegalStateException("Queue full");
 }

offer方法

  public boolean offer(E e) {
     /**   	非空检查
       *   private static void checkNotNull(Object v) {
       *    if (v == null)
       *      throw new NullPointerException();
       *   }
       */
      checkNotNull(e);
      final ReentrantLock lock = this.lock;
      lock.lock();
      try {
          if (count == items.length)
              return false;
          else {
              insert(e);
              return true;
          }
      } finally {
          lock.unlock();
      }
  }
  
  private void insert(E x) {
    putIndex处插入元素
    items[putIndex] = x;
    /**
        putIndex索引插入到数组尾部,重置索引为0
        final int inc(int i) {
           return (++i == items.length) ? 0 : i;
        }
    */
    putIndex = inc(putIndex);
    记录数组中元素个数
    ++count;
    插入成功唤醒,获取元素take方法停止的线程
    notEmpty.signal();
  }

poll方法

    public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : extract();
        } finally {
            lock.unlock();
        }
    }
	private E extract() {
	   final Object[] items = this.items;
	   获取takeIndex处的元素
	   E x = this.<E>cast(items[takeIndex]);
	   清空takeIndex索引处存储的引用
	   items[takeIndex] = null;
	   /**
	     takeIndex索引插入到数组尾部,重置索引为0
	     final int inc(int i) {
           return (++i == items.length) ? 0 : i;
         }
	   */
	   takeIndex = inc(takeIndex);
	   记录数组中元素个数
	   --count;
	   唤醒put方法对应的插入线程
	   notFull.signal();
	   return x;
	}

put方法

  put方法等待在notFull这个Condition上
  public void put(E e) throws InterruptedException {
      checkNotNull(e);
      final ReentrantLock lock = this.lock;
      lock.lockInterruptibly();
      try {
          while (count == items.length)
               notFull.await();
          insert(e);
      } finally {
          lock.unlock();
      }
  }

take方法

    take等待在notEmpty这个Condition
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();
        }
    }

总结

1.ArrayBlockingQueue不可以插入null
2.只能存储固定数目的数据
3.java8以后ArrayBlockingQueue引入了若引用WeakReference,能力有限有待研究

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值