魔塔模拟器
127.28M · 2026-02-27
public interface Collection {
int size();
boolean isEmpty();
}
public interface BlockingQueue<E> extends Collection {
/**
* 入队阻塞
* @param e 待入队的元素
*/
void offer(E e) throws InterruptedException;
/**
* 入队阻塞可超时
* @param e 待入队的元素
*/
void offer(E e, long timeout) throws InterruptedException;
/**
* 出队阻塞
* @return 当前头部元素
*/
E poll() throws InterruptedException;
/**
* 出队阻塞可超时
* @return 当前头部元素
*/
E poll(long timeout) throws InterruptedException;
}
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ArrayBlockingQueue<E> implements BlockingQueue<E> {
private final E[] data;
private int head;
private int tail;
private final AtomicInteger size = new AtomicInteger();
private final ReentrantLock headLock = new ReentrantLock();
private final ReentrantLock tailLock = new ReentrantLock();
private final Condition headWaits = headLock.newCondition();
private final Condition tailWaits = tailLock.newCondition();
@SuppressWarnings("unchecked")
public ArrayBlockingQueue(int capacity) {
this.data = (E[]) new Object[capacity];
}
private boolean fulled() {
return size.get() == data.length;
}
@Override
public void offer(E e) throws InterruptedException {
int s;
tailLock.lockInterruptibly();
try {
while (fulled()) {
tailWaits.await();
}
data[tail] = e;
if (++tail == data.length) {
tail = 0;
}
s = size.getAndIncrement();
if (s < data.length - 1) {
tailWaits.signal();
}
} finally {
tailLock.unlock();
}
if (s == 0) {
headLock.lock();
try {
headWaits.signal();
} finally {
headLock.unlock();
}
}
}
@Override
public void offer(E e, long timeout) throws InterruptedException {
long t = TimeUnit.MILLISECONDS.toNanos(timeout);
int s;
tailLock.lockInterruptibly();
try {
while (fulled()) {
t = tailWaits.awaitNanos(t);
}
data[tail] = e;
// reset tail
if (++tail == data.length) {
tail = 0;
}
s = size.getAndIncrement();
if (s < data.length - 1) {
tailWaits.signal();
}
} finally {
tailLock.unlock();
}
if (s == 0) {
headLock.lock();
try {
headWaits.signal();
} finally {
headLock.unlock();
}
}
}
@Override
public E poll() throws InterruptedException {
E e;
int s;
headLock.lockInterruptibly();
try {
while (isEmpty()) {
headWaits.await();
}
e = data[head];
data[head] = null; // help GC
// reset head
if (++head == data.length) {
head = 0;
}
s = size.getAndDecrement();
if (s > 1) {
headWaits.signal();
}
} finally {
headLock.unlock();
}
if (s == data.length) {
tailLock.lock();
try {
tailWaits.signal();
} finally {
tailLock.unlock();
}
}
return e;
}
@Override
public E poll(long timeout) throws InterruptedException {
E e;
int s;
long t = TimeUnit.MILLISECONDS.toNanos(timeout);
headLock.lockInterruptibly();
try {
while (isEmpty()) {
t = headWaits.awaitNanos(t);
}
e = data[head];
data[head] = null; // help GC
// reset head
if (++head == data.length) {
head = 0;
}
s = size.getAndDecrement();
if (s > 1) {
headWaits.signal();
}
} finally {
headLock.unlock();
}
if (s == data.length) {
tailLock.lock();
try {
tailWaits.signal();
} finally {
tailLock.unlock();
}
}
return e;
}
@Override
public int size() {
return size.get();
}
@Override
public boolean isEmpty() {
return size.get() == 0;
}
@Override
public String toString() {
return Arrays.toString(data);
}
}