package tech.pjx.Test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 实现一个阻塞队列
* @author void
*
*/
public class BlockQueue<T> {
private int size; // 队列长度
private Object[] queue; // 实际队列内容
private int addIndex; // 插入元素的位置
private int removeIndex; // 删除元素的位置
private int curLen; // 实际的元素个数
private Lock lock = new ReentrantLock(); // 全局锁
private Condition isFull = lock.newCondition();
private Condition isEmpty = lock.newCondition();
public BlockQueue(int size){
this.size = size;
queue = new Object[size];
}
public void push(T element) throws InterruptedException {
lock.lock(); // 获取全局锁,保证阻塞队列的线程安全性
try {
while(curLen == size) {
isFull.await(); // 当队列满时,不可再插入元素,线程需在此等待
}
queue[addIndex] = element;
if(++addIndex == size) // 当下标走到数组末尾时,回到数组开头
addIndex = 0;
curLen++;
isEmpty.signal(); // 唤醒等待在pop()的线程
} finally {
lock.unlock(); // ReentrantLock在抛出异常时,不会释放锁,所以必须放在finally块中
}
}
public T pop() throws InterruptedException {
lock.lock();
try {
while(curLen == 0) { // 当队列为空,不可remove元素
isEmpty.await();
}
Object obj = queue[removeIndex];
if(++removeIndex == size)
removeIndex = 0;
curLen--;
isFull.signal(); // 唤醒等待在push()的线程
return (T) obj;
} finally {
lock.unlock();
}
}
}
手撕阻塞队列
最新推荐文章于 2024-04-11 10:54:58 发布