这是一个相当大的问题,因为我们需要访问使用DelayQueue如果我们要继承它或委托给它,并且锁是私人在DelayQueue内部锁。
我们不能用第二个锁定,因为这会导致与take
问题。你也许可以自己实现这一点,但是这样做比自己实现DelayQueue还要多,所以这可能不是你想要的。
我们可以使用反射来访问锁。但请注意,这不是最好的想法,因为它依赖于DelayQueue的实现细节。它可能不适用于所有的JRE,甚至可能会因为您更改运行的JRE版本而中断。这就是说,我认为这是解决您的问题最简单的方法,尽管有点肮脏。
/**
* Bounded implementation of {@link DelayQueue}. This implementation uses
* reflection to access the internal lock in {@link DelayQueue} so might
* only work on the Oracle 1.8 JRE.
* @param <T>
*/
public class BoundedDelayQueue<T extends Delayed> extends DelayQueue<T> {
// Lock used to synchronize every operation
private final transient ReentrantLock lock;
// The limit
private final int limit;
BoundedDelayQueue(int limit) {
try {
// Grab the private lock in DelayQueue using reflection so we can use it
// to gain exclusive access outside of DelayQueue
Field lockField = DelayQueue.class.getDeclaredField("lock");
lockField.setAccessible(true);
this.lock = (ReentrantLock) lockField.get(this);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new Error("Could not access lock field", e);
}
this.limit = limit;
}
@Override
// All the various ways of adding items in DelayQueue delegate to
// offer, so we only have to override it and not the other methods
public boolean offer(final T t) {
// Lock the lock
lock.lock();
try {
// Check the size limit
if(size() == limit) {
return false;
}
// Forward to superclass
return super.offer(t);
} finally {
lock.unlock();
}
}
}
请注意,这不以超时实现offer
,如果你需要,你必须自己做。
当队列已满时,是否要等到空间可用并添加到队列中?什么是延迟? –
延迟与队列容量无关,一个元素只能在时间到期时从队列中取出。检查队列的目的是满的是我想要统计被丢弃的事件的数量。 – haifzhan
您可以在添加或子类DelayQueue以使offer()执行此操作之前检查大小()。 –