java.util.concurrent.ArrayBlockingQueue

来源:互联网 发布:房地产行业 黑心 知乎 编辑:程序博客网 时间:2024/05/22 15:38

 

ArrayBlockingQueue

 使用示例:

ArrayBlockingQueue<String> aq = new ArrayBlockingQueue<String>(5);aq.add("xx3");try {aq.put("cc");} catch (InterruptedException e) {e.printStackTrace();}aq.offer("xx");try {aq.take();} catch (InterruptedException e) {e.printStackTrace();}aq.poll();  

 

ArrayBlockingQueue是一个基于数组、先进先出、线程安全的集合类,其特点是实现指定时间的阻塞读写,并且容量是可以限制的。

1)创建

public ArrayBlockingQueue(int capacity, boolean fair) {if (capacity <= 0)throw new IllegalArgumentException();this.items = (E[]) new Object[capacity];lock = new ReentrantLock(fair);notEmpty = lock.newCondition();notFull = lock.newCondition();}

初始化锁和两个锁上的Condition,一个为notEmpty,一个为notFull。

2)添加

offer(E e , long timeout , TimeUtil unit)

public boolean offer(E e, long timeout, TimeUnit unit)throws InterruptedException {if (e == null) throw new NullPointerException();long nanos = unit.toNanos(timeout);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {for (;;) {if (count != items.length) {insert(e);return true;}if (nanos <= 0)return false;try {nanos = notFull.awaitNanos(nanos);} catch (InterruptedException ie) {notFull.signal(); // propagate to non-interrupted threadthrow ie;}}} finally {lock.unlock();}}

这个方法将元素插入数组的末尾,如果数组满,则进入等待,只到以下三种情况发生才继续:

被唤醒、达到指定的时间、当前线程被中断。

该方法首先将等待时间转换成纳秒。然后加锁,如果数组未满,则在末尾插入数据,如果数组已满,则调用notFull.awaitNanos进行等待。如果被唤醒或超时,重新判断是否满。如果线程被interrupt,则直接抛出异常。

另外一个不带时间的offer方法在数组满的情况下不进去等待,而是直接返回false。

public boolean offer(E e) {if (e == null) throw new NullPointerException();final ReentrantLock lock = this.lock;lock.lock();try {if (count == items.length)return false;else {insert(e);return true;}} finally {lock.unlock();}}

同时还可以选择put方法,此方法在数组已满的情况下会一直等待,知道数组不为空或线程被interrupt。

public void put(E e) throws InterruptedException {if (e == null) throw new NullPointerException();final E[] items = this.items;final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {try {while (count == items.length)notFull.await();} catch (InterruptedException ie) {notFull.signal(); // propagate to non-interrupted threadthrow ie;}insert(e);} finally {lock.unlock();}}

3)获取

poll(long timeout, TimeUnit unit)

public E poll(long timeout, TimeUnit unit) throws InterruptedException {long nanos = unit.toNanos(timeout);final ReentrantLock lock = this.lock;lock.lockInterruptibly();try {for (;;) {if (count != 0) {E x = extract();return x;}if (nanos <= 0)return null;try {nanos = notEmpty.awaitNanos(nanos);} catch (InterruptedException ie) {notEmpty.signal(); // propagate to non-interrupted threadthrow ie;}}} finally {lock.unlock();}}

poll获取队列中的第一个元素,如果队列中没有元素,则进入等待。

poll首先将制定timeout转换成纳秒,然后加锁,如果数组个数不为0,则从当前对象数组中获取最后一个元素,在获取后将位置上的元素置为null。

如果数组中的元素个数为0,首先判断timeout是否小于等于0,若小于0则直接返回null。若大于则进行等待,如果被唤醒或者超时,重新判断数据元素个数是否大于0。

如果线程被interrupt,则直接抛出InterruptedException。

和offer一样,不带时间的poll方法在数组元素个数为0直接返回null,不进行等待。

take方法在数据为空的情况下会一直等待,只到数组不为空或者interrupt。


应用场景在哪呢?

原创粉丝点击