這是一個相當大的問題,因爲我們需要訪問使用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()執行此操作之前檢查大小()。 –