BlockingQueues和线程访问顺序

时间:2013-08-27 14:09:04

标签: java multithreading queue

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

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

谢谢!

注意:我过去曾为此类事情编写过自己的实现,但我想知道Java中的BlockingQueue实现是否会为我做这个。

3 个答案:

答案 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

javadoc

  

此类的构造函数接受可选的fairness参数。   当设置为true时,在争用下,锁有利于授予访问权限   最长等待的线程。 否则此锁不保证任何   特定访问顺序。使用公平锁的程序由许多人访问   线程可以显示较低的总吞吐量(即,较慢;通常   比使用默认设置的那些慢得多,但要小一些   获得锁定的时间差异并保证缺乏饥饿。   但请注意,锁的公平性并不能保证公平性   线程调度。因此,使用公平锁定的许多线程之一可以   在其他活动线程连续多次连续获取它   没有进展,目前没有锁定。还要注意   不定时的tryLock方法不尊重公平性设置。它会   如果即使其他线程正在等待锁定也可以成功。

答案 1 :(得分:2)

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

至少ArrayBlockingQueue告知公平性如下:

  

此类支持订购等待的可选公平策略   生产者和消费者线程。默认情况下,此顺序不是   保证。但是,将公平性设置为true的队列构造   以FIFO顺序授予线程访问权限。公平性普遍下降   吞吐量但减少变异并避免饥饿。

答案 2 :(得分:1)

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