基于JDK的ReentrantLock实现BlockingQueue
BlockingQueue定义接口
/**
* @author SurfingMaster
* @date 2023/8/18
**/
public interface BlockingQueue<E> {
void offer(E e) throws InterruptedException;
boolean offer(E e, long milliSecs) throws InterruptedException;
E poll() throws InterruptedException;
}
接口实现
注意事项
- 避免死锁
/**
* TODO 阻塞、扩容
* @author SurfingMaster
* @date 2023/8/18
**/
public class BlockingQueue03<E> implements BlockingQueue<E> {
private final E[] arr;
private int head = 0;
private int tail = 0;
private final AtomicInteger size = new AtomicInteger(0);
private final ReentrantLock tailLock = new ReentrantLock(); // offerLock
private final Condition tailWaits = tailLock.newCondition();
private final ReentrantLock headLock = new ReentrantLock(); // pollLock
private final Condition headWaits = tailLock.newCondition();
@SuppressWarnings("all")
public BlockingQueue03(int capacity) {
this.arr = (E[]) new Object[capacity];
}
@Override
public void offer(E e) throws InterruptedException {
tailLock.lockInterruptibly();
int cnt;
try {
while (isFull()) {
tailWaits.await();
}
arr[tail] = e;
if (++tail == arr.length) {
tail = 0;
}
cnt = size.getAndIncrement();
if (cnt < arr.length - 1) {
tailWaits.signal();
}
} finally {
tailLock.unlock();
}
// 避免锁中锁
if (cnt == 0) {
headLock.lock();
try {
headWaits.signal();
} finally {
headLock.unlock();
}
}
}
@Override
public boolean offer(E e, long milliSecs) throws InterruptedException {
tailLock.lockInterruptibly();
int cnt;
try {
long remainTime = TimeUnit.DAYS.toNanos(milliSecs);
while (isFull()) {
if (remainTime <= 0) return false;
remainTime = tailWaits.awaitNanos(remainTime);
}
arr[tail] = e;
if (++tail == arr.length) {
tail = 0;
}
cnt = size.getAndIncrement();
if (cnt < arr.length - 1) {
tailWaits.signal();
}
} finally {
tailLock.unlock();
}
// 避免锁中锁
if (cnt == 0) {
headLock.lock();
try {
headWaits.signal();
} finally {
headLock.unlock();
}
}
return true;
}
@Override
public E poll() throws InterruptedException {
E res;
int cnt;
headLock.lockInterruptibly();
try {
while (isEmpty()) {
headWaits.await();
}
res = arr[head];
arr[head] = null;
if (++head == arr.length) {
head = 0;
}
cnt = size.getAndDecrement();
if (cnt > 1) {
headWaits.signal();
}
} finally {
headLock.unlock();
}
// 避免锁中锁
if (cnt == arr.length) {
try {
tailLock.lock();
tailWaits.signal();
} finally {
tailLock.unlock();
}
}
return res;
}
public boolean isEmpty() {
return size.get() == 0;
}
public boolean isFull() {
return size.get() == arr.length;
}
}