@Slf4j(topic = "c.BlockingDeque")
class BlockingDeque<T> {
private Deque<T> deque = new ArrayDeque<>();
private ReentrantLock lock = new ReentrantLock();
//消费者阻塞队列
private Condition emptyWaitCondition = lock.newCondition();
//生产者阻塞队列
private Condition fullWaitCondition = lock.newCondition();
private int capacity;
public BlockingDeque(int capacity) {
this.capacity = capacity;
}
//带超时的阻塞获取
public T poll(long timeout, TimeUnit unit) {
lock.lock();
try{
long nanos = unit.toNanos(timeout);
while (deque.isEmpty()) {
try {
//返回的是剩余的时间,这样可以排除虚假唤醒的问题
if (nanos <= 0) {
return null;
}
nanos = emptyWaitCondition.awaitNanos(nanos);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
T t = deque.removeFirst();
fullWaitCondition.signal();
return t;
} finally {
lock.unlock();
}
}
public T take() {
lock.lock();
try {
while (deque.isEmpty()) {
try {
emptyWaitCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
T t = deque.removeFirst();
fullWaitCondition.signal();
return t;
} finally {
lock.unlock();
}
}
public void put(T element) {
lock.lock();
try {
while (deque.size() == capacity) {
try {
//使main线程
log.debug("等待加入任务队列:{}",element);
fullWaitCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("加入任务队列:{}",element);
deque.addLast(element);
emptyWaitCondition.signal();
} finally {
lock.unlock();
}
}
//带超时时间的阻塞添加
public boolean offer(T element,long timeout,TimeUnit unit) {
lock.lock();
try {
long nanos = unit.toNanos(timeout);
while (deque.size() == capacity) {
try {
if (nanos <= 0) {
return false;
}
//使main线程进入等待
log.debug("等待加入任务队列:{}",element);
nanos = fullWaitCondition.awaitNanos(nanos);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
log.debug("加入任务队列:{}",element);
deque.addLast(element);
emptyWaitCondition.signal();
return true;
} finally {
lock.unlock();
}
}
public int size() {
lock.lock();
try {
return deque.size();
} finally {
lock.unlock();
}
}
public void tryout(RejectPolicy<T> rejectPolicy,T element) {
lock.lock();
try {
if (deque.size() == capacity) {
rejectPolicy.reject(this,element);
} else {
log.debug("加入任务队列:{}",element);
deque.addLast(element);
emptyWaitCondition.signal();
}
} finally {
lock.unlock();
}
}
}