你的位置:首页 > Java教程

[Java教程]【JAVA并发编程实战】12、使用condition实现多线程下的有界缓存先进先出队列


package cn.study.concurrency.ch14;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * 使用condition作为挂起线程的信号 * 这个是先进先出的队列 * @author xiaof * * @param <T> */public class ConditionBoundedBuffer<T> {  protected final Lock lock = new ReentrantLock();  //数据队列长度  private static final int BUFFER_SIZE = 1024;  //建立两个condition,一个代表不为空,一个代表不满  private final Condition notFull = lock.newCondition();  private final Condition notEmpty = lock.newCondition();  private final T[] items = (T[]) new Object[BUFFER_SIZE];  private int tail, head, count;    public void put(T x) throws InterruptedException  {    lock.lock();//这里在进行操作的时候上锁    try {      while(count == items.length)      {        //如果是满的就挂起线程,等待变为notFull        notFull.await();      }      items[tail] = x;      //判断是否是已经达到了满队列的情况      if(++tail == items.length)        tail = 0;      //计数值++      ++count;      //插入数据,队列肯定不是空的,那么进行非空信号发布      notEmpty.signal();    } finally{      //执行完毕,切记一定要解锁      lock.unlock();    }  }    //获取数据,阻塞直到队列中有数据为止  public T take() throws InterruptedException  {    lock.lock();//进行操作之前,先上锁        try {      while(count == 0)      {        //如果队列中没有数据,那么就要进行现场挂起        notEmpty.await();      }      //得到数据,用来返回      T t = items[head];      items[head] = null;//吧输出出去的数据设为空      if(++head == items.length)        head = 0; //重置队里索引      --count;  //计数减一      notFull.signal();//唤醒插入操作,因为获取出去一个数据,那么队列就一定有空位      return t;    } finally {      //切记在执行完毕之后,不论成功与否,都要解锁      lock.unlock();    }  }  }