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();
}
} }