我们如何维护有界阻塞队列中元素的顺序



队列根据其定义应该是FIFO类型的结构。虽然我们将其设为阻塞,但这意味着当队列的大小等于队列大小的MAX_LIMIT时,添加新元素时可能会阻塞几个线程。现在,如果一个元素从队列中退出,我们如何确保第一次等待的线程能够执行。

如果您阅读特定实现的文档,您会发现:

  • ArrayBlockingQueue

    此类支持可选的公平性策略,用于订购等待的生产者和消费者线程。默认情况下,不保证此订购。然而,公平性设置为true的队列按照FIFO顺序授予线程访问权限。公平通常会降低吞吐量,但会降低可变性并避免饥饿。

  • LinkedBlockingQueue

    没有公平保障。

  • SynchronousQueue

    此类支持可选的公平性策略,用于订购等待的生产者和消费者线程。默认情况下,不保证此订购。然而,公平性设置为true的队列按照FIFO顺序授予线程访问权限。

有关常规队列类如何处理此问题的摘要,请参阅@Andreas的回答。

但我将提出另一种看待这一问题的方法。

您提出了一种场景,其中线程由于无法添加到队列而被阻塞。如果发生这种情况,那么从性能角度来看,最大的问题是被阻塞线程使用/持有的资源和锁。

一般来说,有两个可能的原因:

  1. 添加和删除队列条目的速率之间存在短期不平衡。这可以通过简单地增加队列边界来解决。

  2. 添加和删除队列条目的速率之间存在长期不平衡。这只能通过添加更多的使用者线程和/或删除工作线程来解决。

关键是,如果你可以让线程不需要阻塞,你就不需要担心阻塞线程的公平性。


另一个问题是公平是否真的很重要。以严格公平的方式将条目添加到队列中真的重要吗?它是否会影响应用程序的正确性?(用户是否能够判断他们的请求何时被推迟……或超过另一个用户的请求?(

(我可以想象一些要求严格公平的场景。但它们只是极少数。(

如果要求严格的公平性,那么在请求被添加到队列之前对请求的处理又如何呢。那个也需要公平吗?因为JVM和操作系统没有提供任何保证线程调度是公平的。


基本上,使请求处理完全公平是一个棘手的问题。因此,对于大多数场景来说,实现FIFO队列提交的严格公平性几乎没有意义。

最新更新