我试图理解java.util.concurrent
中的DelayQueue
,但是leader
让我困惑。
首先,我们可以实现一个没有 leader
的 DelayQueue,如下所示:
public boolean offer(E e) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
q.offer(e);
if (q.peek() == e) {
available.signal();
}
return true;
} finally {
lock.unlock();
}
}
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
for (;;) {
E first = q.peek();
if (first == null) {
available.await();
} else {
long delay = first.getDelay(TimeUnit.NANOSECONDS);
if (delay <= 0) {
return q.poll();
} else {
available.awaitNanos(delay);
}
}
}
} finally {
lock.unlock();
}
}
其次,它似乎并没有最大限度地减少不必要的定时等待。根据注释:
This variant of the Leader-Follower pattern (http://www.cs.wustl.edu/~schmidt/POSA/POSA2/) serves to minimize unnecessary timed waiting
我认为这是最小化awaitNanos
(使用await
而不是awaitNanos
),但我真的对此表示怀疑。如果新元素不是队列的头部,则不会向任何线程发出信号。 (参见下面的offer
方法)
if (q.peek() == e) {
leader = null; // set leader to null
available.signal();
}
所以只有当新元素是头部时才会有区别。但在这种情况下,leader
将被设置为 null
,并且发出信号的线程不会走这条路(take
方法):
else if (leader != null)
available.await();
线程将始终执行awaitNanos
。
那么,有人可以向我解释一下吗?我是否在某个地方得到了错误的想法?
最佳答案
根据源码注释:
It waits only for the next delay to elapse, but other threads await indefinitely.
领导者不用于 minimizing awaitNanos
,用于避免不必要的唤醒和 sleep 。如果让所有线程 available.awaitNanos(delay)
在take
方法中,它们会被同时调用,但只有一个能真正从队列中获取元素,其他的又会陷入 hibernate ,这是不必要的,而且浪费资源。
采用Leader-Follow模式,领导者available.awaitNanos(delay)
,非引导线程 available.await()
。因此领导者将首先醒来并检索过期的元素,然后在必要时向另一个等待线程发出信号。这样效率更高。
示例
假设我有一个元素 E
在队列中,T
之后就会过期纳秒,并且有两个线程 Thread_1
和Thread_2
.
没有领导者(您在问题中提供的实现)
-
Thread_1
来电take
方法,发现 E 在 T 纳秒后可用,因此调用available.awaitNanos(T)
. -
Thread_2
来电take
方法,发现 E 在 T 纳秒后可用,因此调用available.awaitNanos(T)
.
T
之后纳秒,Thread_1
醒来并服用元素E
。 Thread_2
醒来却什么也没得到,所以它不得不再次 sleep 。 Thread_2
的唤醒和再次 sleep 没有必要。
与领导
-
Thread_1
来电take
方法,发现 E 在 T 纳秒后可用,因此它成为领导者并调用available.awaitNanos(T)
. -
Thread_2
来电take
方法,发现 E 在 T 纳秒后可用,但Thread_2
还注意到已经有一个领导者,所以Thread_2
来电available.await()
.
T
之后纳秒,Thread_1
醒来并服用元素E
。 Thread_2
将 hibernate 直到新元素放入队列。
关于java - DelayQueue中的leader到底是做什么用的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48493830/