java BlockingQueue之ArrayBlockingQueue

来源:互联网 发布:素数判断 c语言 编辑:程序博客网 时间:2024/04/28 16:27
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 元素。试图 addputoffer 一个 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(); }}


 

 


 

原创粉丝点击