java - DelayQueue中的leader到底是做什么用的?

标签 java multithreading concurrency java.util.concurrent blockingqueue

我试图理解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_1Thread_2 .

没有领导者(您在问题中提供的实现)

  • Thread_1来电 take方法,发现 E 在 T 纳秒后可用,因此调用 available.awaitNanos(T) .
  • Thread_2来电 take方法,发现 E 在 T 纳秒后可用,因此调用 available.awaitNanos(T) .

T之后纳秒,Thread_1醒来并服用元素EThread_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醒来并服用元素EThread_2将 hibernate 直到新元素放入队列。

关于java - DelayQueue中的leader到底是做什么用的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48493830/

相关文章:

python - Python中的可中断线程连接

java - 从java中的xpath表达式中提取所有变量引用的最安全方法

java - 如何开始学习大数据?作为开发人员,我需要专注于哪些模块

java - 调整 JFrame 的大小以适应添加的组件

java - Vector 中的并发线程 (Java)

c# - 如何在 ASP.NET MVC Web 应用程序中使用 log4net 异步登录而不用尽所有可用线程?

java - 使用Java线程从并发访问切换到顺序访问

Scala SyncVar isDefined 标志的使用

java - 网络应用程序 : safetly update a shared List/Map in the AppContext

java - 平板电脑的客户端服务器框架