5

我有一种情况,多个线程将通过调用来轮询单个BlockingQueuetake()。我想知道的是:

如果多个线程正在等待队列接收一个项目,它们是否会按照它们调用的顺序优先从队列中取出项目,take()或者线程从队列中取出项目的顺序是任意的?

谢谢!

注意:过去我已经为这种事情编写了自己的实现,但我想知道BlockingQueueJava 中的实现是否会为我做这件事。

4

3 回答 3

4

这取决于实施。

如果您使用 a LinkedBlockingQueue,该take()方法将使用 aReentrantLock

public E take() throws InterruptedException {
    E x;
    int c = -1;
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lockInterruptibly();
    ...
}

// declared as
private final ReentrantLock takeLock = new ReentrantLock(); // no fairness argument, defaults to false

javadoc说_

此类的构造函数接受一个可选的公平参数。当设置为 true 时,在争用情况下,锁有利于授予对等待时间最长的线程的访问权限。否则,此锁不保证任何特定的访问顺序. 使用由许多线程访问的公平锁的程序可能会显示出比使用默认设置的程序更低的整体吞吐量(即,更慢;通常要慢得多),但在获取锁和保证不会出现饥饿的情况下具有较小的时间差异。但是请注意,锁的公平性并不能保证线程调度的公平性。因此,使用公平锁的许多线程之一可能会连续多次获得它,而其他活动线程没有进展并且当前没有持有锁。另请注意,不定时的 tryLock 方法不遵守公平设置。如果锁可用,即使其他线程正在等待,它也会成功。

于 2013-08-27T14:16:41.323 回答
2

在许多情况下,javadocs 会提到该类是否“公平”,即阻塞是分布式的,以便所有线程获得相同的机会。然而,这并不一定意味着与“以相同的顺序”相同。检查您的特定队列实现的 javadocs 以查看它是否包含有关公平和/或顺序的信息。

至少ArrayBlockingQueue告知公平性如下:

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

于 2013-08-27T14:15:36.067 回答
1

这取决于实现,一个类是否支持用于排序等待生产者和消费者线程的可选公平策略。例如,ArrayBlockingQueue 可以是公平的,因为它具有构造函数 ArrayBlockingQueue(int capacity, boolean fair),但 LinkedBlockingQueue 不能。

于 2013-08-27T14:22:52.237 回答