java BlockingQueue之ArrayBlockingQueue

JAVA API中这样解释BlockingQueue:

支持两个附加操作的 Queue,这两个操作是:获取元素时等待队列变为非空,以及存储元素时等待空间变得可用。

BlockingQueue 方法以四种形式出现,对于不能立即满足但可能在将来某一时刻可以满足的操作,这四种形式的处理方式不同:第一种是抛出一个异常,第二种是返回一个特殊值(nullfalse,具体取决于操作),第三种是在操作可以成功前,无限期地阻塞当前线程,第四种是在放弃前只在给定的最大时间限制内阻塞。下表中总结了这些方法:

 抛出异常特殊值阻塞超时
插入add(e)offer(e)put(e)offer(e, time, unit)
移除remove()poll()take()poll(time, unit)
检查element()peek()不可用不可用

BlockingQueue 不接受 null 元素。试图 addput offer 一个 null 元素时,某些实现会抛出 NullPointerExceptionnull 被用作指示poll 操作失败的警戒值。

先看一个简单的实现例子:

public class BoundedBuffer {

 //可中断同步锁
 final Lock lock = new ReentrantLock();
 final Condition notFull = lock.newCondition();
 final Condition notEmpty = lock.newCondition();

 final Object[] items = new Object[100];
 int putptr, takeptr, count;

 public void put(Object x) throws InterruptedException {
  lock.lock();
  try {
   while (count == items.length)
    notFull.await();
   items[putptr] = x;
   if (++putptr == items.length)
    putptr = 0;
   ++count;
   notEmpty.signal();
  } finally {
   lock.unlock();
  }
 }

 public Object take() throws InterruptedException {
  lock.lock();
  try {
   while (count == 0)
    notEmpty.await();
   Object x = items[takeptr];
   if (++takeptr == items.length)
    takeptr = 0;
   --count;
   notFull.signal();
   return x;
  } finally {
   lock.unlock();
  }
 }

}

上面的例子展示了一个定长的队列,提供了存放和提取数据的方法,且使用ReentrantLock来实现同步。
再来看看SUN的实现:

private static final long serialVersionUID = -817911632652898426L;
  private final E[] items;
  private int takeIndex;
  private int putIndex;
  private int count;
  private final ReentrantLock lock;
  private final Condition notEmpty;
  private final Condition notFull;

public ArrayBlockingQueue(int paramInt)
  {
    this(paramInt, false);
  }
  //初始构造函数
  public ArrayBlockingQueue(int paramInt, boolean paramBoolean)
  {
    if (paramInt <= 0)
      throw new IllegalArgumentException();
    this.items = ((Object[])new Object[paramInt]);
    //初始化锁对象
    this.lock = new ReentrantLock(paramBoolean);
    this.notEmpty = this.lock.newCondition();
    this.notFull = this.lock.newCondition();
  }
  //put的实现
  public void put(E paramE)
    throws InterruptedException
  {
    if (paramE == null)
      throw new NullPointerException();
    Object[] arrayOfObject = this.items;
    ReentrantLock localReentrantLock = this.lock;
    //如果当前线程未被中断则获取锁
    localReentrantLock.lockInterruptibly();
    try
    {
      try
      {
        while (this.count == arrayOfObject.length)
          //数组已满 等待直到被唤醒或中断
          this.notFull.await();
      }
      catch (InterruptedException localInterruptedException)
      {
        //被中断则唤醒
        this.notFull.signal();
        throw localInterruptedException;
      }
      insert(paramE);
    }
    finally
    {
      localReentrantLock.unlock();
    }
  }
  private void insert(E paramE)
  {
    this.items[this.putIndex] = paramE;
    this.putIndex = inc(this.putIndex);
    this.count += 1;
    //唤醒持有notEmpty等待的线程
    this.notEmpty.signal();
  }
  
  public E take()
    throws InterruptedException
  {
    ReentrantLock localReentrantLock = this.lock;
    //获取锁
    localReentrantLock.lockInterruptibly();
    try
    {
      try
      {
        while (this.count == 0)
        //空则等待
          this.notEmpty.await();
      }
      catch (InterruptedException localInterruptedException)
      {
      //唤醒
        this.notEmpty.signal();
        throw localInterruptedException;
      }
      Object localObject1 = extract();
      Object localObject2 = localObject1;
      return localObject2;
    }
    finally
    {
      localReentrantLock.unlock();
    }
  }
  
  private E extract()
  {
    Object[] arrayOfObject = this.items;
    Object localObject = arrayOfObject[this.takeIndex];
    arrayOfObject[this.takeIndex] = null;
    this.takeIndex = inc(this.takeIndex);
    this.count -= 1;
    //唤醒等待的线程
    this.notFull.signal();
    return localObject;
  }


 

 

public ArrayBlockingQueue(int paramInt)
  {
    this(paramInt, false);
  }
  //初始构造函数
  public ArrayBlockingQueue(int paramInt, boolean paramBoolean)
  {
    if (paramInt <= 0)
      throw new IllegalArgumentException();
    this.items = ((Object[])new Object[paramInt]);
    //初始化锁对象
    this.lock = new ReentrantLock(paramBoolean);
    this.notEmpty = this.lock.newCondition();
    this.notFull = this.lock.newCondition();
  }
  //put的实现
  public void put(E paramE)
    throws InterruptedException
  {
    if (paramE == null)
      throw new NullPointerException();
    Object[] arrayOfObject = this.items;
    ReentrantLock localReentrantLock = this.lock;
    //如果当前线程未被中断则获取锁
    localReentrantLock.lockInterruptibly();
    try
    {
      try
      {
        while (this.count == arrayOfObject.length)
          //数组已满 等待直到被唤醒或中断
          this.notFull.await();
      }
      catch (InterruptedException localInterruptedException)
      {
        //被中断则唤醒
        this.notFull.signal();
        throw localInterruptedException;
      }
      insert(paramE);
    }
    finally
    {
      localReentrantLock.unlock();
    }
  }
  private void insert(E paramE)
  {
    this.items[this.putIndex] = paramE;
    this.putIndex = inc(this.putIndex);
    this.count += 1;
    //唤醒持有notEmpty等待的线程
    this.notEmpty.signal();
  }
  
  public E take()
    throws InterruptedException
  {
    ReentrantLock localReentrantLock = this.lock;
    //获取锁
    localReentrantLock.lockInterruptibly();
    try
    {
      try
      {
        while (this.count == 0)
        //空则等待
          this.notEmpty.await();
      }
      catch (InterruptedException localInterruptedException)
      {
      //唤醒
        this.notEmpty.signal();
        throw localInterruptedException;
      }
      Object localObject1 = extract();
      Object localObject2 = localObject1;
      return localObject2;
    }
    finally
    {
      localReentrantLock.unlock();
    }
  }
  
  private E extract()
  {
    Object[] arrayOfObject = this.items;
    Object localObject = arrayOfObject[this.takeIndex];
    arrayOfObject[this.takeIndex] = null;
    this.takeIndex = inc(this.takeIndex);
    this.count -= 1;
    //唤醒等待的线程
    this.notFull.signal();
    return localObject;
  }

以上只贴出了部分源码,ArrayBlockingQueue还提供了其他三种处理方式,有兴趣的可以自己去研读。

 

下面是一个小例子:

public class Setup {
 class Producer implements Runnable {
  volatile int i=0;
     private final BlockingQueue<String> queue;
     public Producer(BlockingQueue<String> q) { queue = q; }
     public void run() {
      try {
       while(true&&i<1000) { 
        queue.put(produce());
       }
      } catch (InterruptedException ex) 
      {
       ex.printStackTrace();
      }
     }
    String produce(){
     i++;
     return "put"+i;
    }
 }

 class Consumer implements Runnable {
  private final BlockingQueue<String> queue;
     Consumer(BlockingQueue<String> q) { queue = q; }
     public void run() {
      try {
       while(true) { 
        synchronized (lock) {
         System.out.println(queue.take()); 
     }
        
       }
      } catch (InterruptedException ex) 
      { 
       ex.printStackTrace();
      }
     }
  }

 Object lock = new Object();
   
 public static void main(String args[]){
  Setup s = new Setup();
  BlockingQueue<String> q = new ArrayBlockingQueue<String>(1);
     Producer p = s.new Producer(q);
     Consumer c1 = s.new Consumer(q);
     Consumer c2 = s.new Consumer(q);
     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
 }
}


 

 


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值