我试图理解DelayQueue
中的java.util.concurrent
,但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();
}
}
其次,似乎并没有减少不必要的定时等待。根据注解:
我认为这是使
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
。那么,有人可以向我解释吗?我在某个地方弄错了主意吗?
最佳答案
根据源代码的注释:
该领导者不用于minimizing awaitNanos
,它用于避免不必要的唤醒和 sleep 。如果让所有线程available.awaitNanos(delay)
用take
方法,它们将被同时调用,但是只有一个线程可以真正从队列中获取元素,其他线程将再次进入休眠状态,这是不必要的并且浪费资源。
使用Leader-Follower模式,领导者available.awaitNanos(delay)
和非领导者线程available.await()
。因此,领导者将首先唤醒并检索一个expried元素,然后在必要时发出另一个等待线程的信号。这样更有效。
例子
假设我在队列中有一个元素E
,它将在T
纳秒后过期,并且有两个线程Thread_1
和Thread_2
。
没有领导者(您在问题中提供的实现)
Thread_1
调用take
方法,并在T纳秒后发现E可用,因此调用available.awaitNanos(T)
。 Thread_2
调用take
方法,并在T纳秒后发现E可用,因此调用available.awaitNanos(T)
。 在
T
纳秒后,Thread_1
唤醒并采用E
元素。 Thread_2
醒来后一无所获,因此必须再次休眠。 不需要重新唤醒Thread_2
并休眠。 和组长
Thread_1
调用take
方法,并在T纳秒后发现E可用,因此它成为前导者并调用available.awaitNanos(T)
。 Thread_2
调用take
方法,并在T纳秒后发现E可用,但是Thread_2
也注意到已经存在一个领导者,因此Thread_2
调用available.await()
。 在
T
纳秒后,Thread_1
唤醒并采用E
元素。 Thread_2
将 hibernate ,直到将新元素放入队列中为止。关于java - Leader在DelayQueue中到底用于什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48493830/