1.主要结构 一个用于存放元素的数组
两个Condition 用于阻塞 唤醒 线程
2.代码
public class MyBelokingQueue<E> implements Serializable{
//用于存放元素的数组
Object[] item;
/** 下一个put的索引, offer, or add */
int putIndex;
/** 队列中元素的数量 */
int count;
/**下一个获取元素的下标**/
int takeIndex;
Condition notEmty;
Condition notNull;
ReentrantLock reentrantLock;
public void MyBelokingQueue(int index){
if(index<=0){
throw new IllegalArgumentException();
}
this.item=new Object[index];
this.reentrantLock=new ReentrantLock();
this.notEmty=reentrantLock.newCondition();
this.notNull=reentrantLock.newCondition();
}
@Override
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly(); //可中断的获取锁
try {
while (count == items.length)//当线程从等待中被唤醒时,会比较当前队列是否已经满了
{notFull.await();}//这里可以看到 当数组满了 notFull 就会让当前线程阻塞
enqueue(e);//插入队列的方法
} finally {
lock.unlock();
}
}
}
public void enqueue(E e){
final Object[] items = this.item;
items[putIndex]=e;
//如果当前索引等于数组长度那么 下次从0开始
if(++putIndex==items.length){
putIndex=0;
}
count++; //总数加1
notEmty.signal();//唤醒线程
}
//检查是否是null
public void checkNotNull(E e){
if(e==null){
throw new NullPointerException();
}
}
/**
**************获取元素 take(): 检索并且删除返回队列头的元素,如果元素没有会一直等待,有就返回。
@Override
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();//可中断的锁
try {
while (count == 0) //如果数组里没有元素就阻塞
{notEmpty.await();}//如果 没有获取到元素 就阻塞当前线程
return dequeue();
} finally {
lock.unlock();
}
}
private E dequeue() {
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex]; //获取元素
items[takeIndex] = null;//设置该下标元素为null
if (++takeIndex == items.length)
{takeIndex = 0;}
count--;
if (itrs != null)
{itrs.elementDequeued();}
notFull.signal(); //当元素被消费 队列不满了 就唤醒等待put的线程
return x;
}
}