java.util.concurrent.BlockingQueue ArrayBlockingQueue

一、简介

    BlockingQueue接口定义了一种阻塞的FIFO queue,每一个BlockingQueue都有一个容量,让容量满时往BlockingQueue中添加数据时会造成阻塞,当容量为空时取元素操作会阻塞。ArrayBlockingQueue是对BlockingQueue的一个数组实现,它使用一把全局的锁并行对queue的读写操作,同时使用两个Condition阻塞容量为空时的取操作和容量满时的写操作。

二、具体实现

    ArrayBlockingQueue底层定义如下:

[java] view plain copy
  1. public class ArrayBlockingQueue<E> extends AbstractQueue<E>     
  2.         implements BlockingQueue<E>, java.io.Serializable {     
  3.     
  4.     // 使用循环数组来实现queue,初始时takeIndex和putIndex均为0     
  5.     private final E[] items;     
  6.     private transient int takeIndex;     
  7.     private transient int putIndex;     
  8.     private int count;     
  9.     
  10.     // 用于并发的锁和条件     
  11.    private final ReentrantLock lock;     
  12.     private final Condition notEmpty;     
  13.     private final Condition notFull;     
  14.     
  15.     /**   
  16.      * 循环数组   
  17.      * Circularly increment i.   
  18.      */    
  19.     final int inc(int i) {     
  20.         return (++i == items.length)? 0 : i;     
  21.     }     
  22.     
  23.     public ArrayBlockingQueue(int capacity, boolean fair) {     
  24.         if (capacity <= 0)     
  25.             throw new IllegalArgumentException();     
  26.         this.items = (E[]) new Object[capacity];     
  27.         // 分配锁及该锁上的condition     
  28.         lock = new ReentrantLock(fair);     
  29.         notEmpty = lock.newCondition();     
  30.         notFull =  lock.newCondition();     
  31.     }     
  32.     
  33.   ...     
  34. }    


ArrayBlockingQueue的取操作:

[java] view plain copy
  1. public class ArrayBlockingQueue<E> extends AbstractQueue<E>     
  2.         implements BlockingQueue<E>, java.io.Serializable {     
  3.     
  4.     private E extract() {     
  5.         final E[] items = this.items;     
  6.         E x = items[takeIndex];     
  7.         items[takeIndex] = null;     
  8.         takeIndex = inc(takeIndex);     
  9.         --count;     
  10.        // 激发notFull条件     
  11.         notFull.signal();     
  12.         return x;     
  13.     }     
  14.     
  15.      /**   
  16.         * condition的await的语义如下:   
  17.      * 与condition相关的锁以原子方式释放,并禁用该线程   
  18.      * 方法返回时,线程必须获得与该condition相关的锁   
  19.      */    
  20.     public E take() throws InterruptedException {     
  21.         final ReentrantLock lock = this.lock;     
  22.         lock.lockInterruptibly();     
  23.         try {     
  24.             try {     
  25.                   // 等待notEmpty的条件     
  26.                 while (count == 0)     
  27.                     notEmpty.await();     
  28.             } catch (InterruptedException ie) {     
  29.                 notEmpty.signal(); // propagate to non-interrupted thread     
  30.                 throw ie;     
  31.             }     
  32.             E x = extract();     
  33.             return x;     
  34.         } finally {     
  35.             lock.unlock();     
  36.         }     
  37.     }     
  38.     
  39.   ...     
  40. }    


ArrayBlockingQueue的写操作:

[java] view plain copy
  1. public class ArrayBlockingQueue<E> extends AbstractQueue<E>     
  2.         implements BlockingQueue<E>, java.io.Serializable {     
  3.     
  4.     private void insert(E x) {     
  5.         items[putIndex] = x;     
  6.         putIndex = inc(putIndex);     
  7.         ++count;     
  8.         notEmpty.signal();     
  9.     }     
  10.     
  11.     public void put(E o) throws InterruptedException {     
  12.         if (o == nullthrow new NullPointerException();     
  13.         final E[] items = this.items;     
  14.         final ReentrantLock lock = this.lock;     
  15.         lock.lockInterruptibly();     
  16.         try {     
  17.             try {     
  18.                   // 等待notFull条件     
  19.            while (count == items.length)     
  20.                     notFull.await();     
  21.             } catch (InterruptedException ie) {     
  22.                 notFull.signal(); // propagate to non-interrupted thread     
  23.                 throw ie;     
  24.             }     
  25.             insert(o);     
  26.         } finally {     
  27.             lock.unlock();     
  28.         }     
  29.     }     
  30.     
  31.   ...     
  32. }    


注意:ArrayBlockingQueue在读写操作上都需要锁住整个容器,因此吞吐量与一般的实现是相似的,适合于实现“生产者消费者”模式。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值