我有一种情况,即多个线程将通过调用BlockingQueue来轮询单个take()
。我想知道的是:
如果多个线程正在等待队列接收一个项目,那么它们是否会优先按照它们调用take()
的顺序从队列中取出项目,或者是线程采用的顺序排队的事情是随意的吗?
谢谢!
注意:我过去曾为此类事情编写过自己的实现,但我想知道Java中的BlockingQueue
实现是否会为我做这个。
答案 0 :(得分:4)
这取决于实施。
如果您使用LinkedBlockingQueue
,则take()
方法会检查ReentrantLock
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
此类的构造函数接受可选的fairness参数。 当设置为true时,在争用下,锁有利于授予访问权限 最长等待的线程。 否则此锁不保证任何 特定访问顺序。使用公平锁的程序由许多人访问 线程可以显示较低的总吞吐量(即,较慢;通常 比使用默认设置的那些慢得多,但要小一些 获得锁定的时间差异并保证缺乏饥饿。 但请注意,锁的公平性并不能保证公平性 线程调度。因此,使用公平锁定的许多线程之一可以 在其他活动线程连续多次连续获取它 没有进展,目前没有锁定。还要注意 不定时的tryLock方法不尊重公平性设置。它会 如果即使其他线程正在等待锁定也可以成功。
答案 1 :(得分:2)
在许多情况下,javadocs提到类是否“公平”,即阻塞是分布式的,以便所有线程获得相同的机会。然而,这并不一定意味着“获得相同的顺序”。检查javadocs以查找特定的队列实现,看看它是否包含有关公平性和/或顺序的信息。
至少ArrayBlockingQueue
告知公平性如下:
此类支持订购等待的可选公平策略 生产者和消费者线程。默认情况下,此顺序不是 保证。但是,将公平性设置为true的队列构造 以FIFO顺序授予线程访问权限。公平性普遍下降 吞吐量但减少变异并避免饥饿。
答案 2 :(得分:1)
这取决于实现,类是否支持用于排序等待生成器和消费者线程的可选公平策略。例如。 ArrayBlockingQueue可以公平,因为它有构造函数ArrayBlockingQueue(int capacity,boolean fair),但LinkedBlockingQueue不能。