您应该在哪里使用BlockingQueue实现而不是简单队列实现?

时间:2008-12-11 04:35:47

标签: java queue

我想我会重新构思我的问题

您应该在哪里使用BlockingQueue实现而不是简单队列实现?

BlockingQueue优于队列实现的优点/缺点是什么,考虑到诸如速度,并发性或其他性质等方面的变化,例如:访问最后一个元素的时间。

我使用过这两种队列。我知道Blocking Queue通常用于并发应用程序。我正在编写简单的ByteBuffer池,我需要一个ByteBuffer对象的占位符。我需要最快,线程安全的队列实现。甚至像ArrayList这样的List实现也具有元素的持续访问时间。

任何人都可以讨论BlockingQueue与Queue vs List实现的优缺点吗?

目前我使用ArrayList来保存这些ByteBuffer对象。

我应该使用哪种数据结构来保存这些对象?

4 个答案:

答案 0 :(得分:31)

如果您想要限制某种请求,有限容量BlockingQueue也会有所帮助。通过无限制的队列,生产者可以远远领先于消费者。这些任务最终会被执行(除非它们有很多导致OutOfMemoryError),但是生产者可能早已放弃,因此浪费了精力。

在这样的情况下,最好向潜在的生产者发出队列已满的信号,并快速放弃失败。例如,生产者可能是一个Web请求,用户不想等待太长时间,即使它在等待时不会占用很多CPU周期,也会占用有限的资源,如套接字和一些内存。放弃将使排队的任务更有机会及时完成。


关于修正后的问题,我将其解释为“在游泳池中保存物品有什么好处?”

无界LinkedBlockingQueue是许多游泳池的不错选择。但是,根据您的池管理策略,ConcurrentLinkedQueue也可能有效。

在池化应用程序中,阻止“put”是不合适的。控制队列的最大大小是池管理器的工作 - 它决定何时创建或销毁池的资源。池的客户端从池中借用和返回资源。添加新对象或将先前借用的对象返回池应该是快速,无阻塞的操作。因此,有界容量队列不是池的好选择。

另一方面,从池中检索对象时,大多数应用程序都希望等到资源可用。至少暂时阻止的“接受”操作比“忙等待”更有效 - 重复轮询直到资源可用。在这种情况下,LinkedBlockingQueue是一个不错的选择。借款人可以使用take无限期阻止,或使用poll限制其愿意阻止的时间。

一种不常见的情况,当客户端根本不愿意阻塞时,但如果池为空,则能够为自己创建资源。在这种情况下,ConcurrentLinkedQueue是一个不错的选择。这是一个灰色区域,尽可能多地共享资源(例如,内存),但速度更为重要。在更糟糕的情况下,这会退化为具有自己的资源实例的每个线程;那么不打算尝试在线程之间共享会更有效率。

这两个集合在并发应用程序中提供了良好的性能和易用性。对于非并发应用程序,ArrayList很难被击败。即使对于动态增长的集合,LinkedList的每元素开销也允许带有一些空插槽的ArrayList在内存方面保持竞争力。

答案 1 :(得分:3)

您会在多线程情况下看到BlockingQueue。例如,如果要使用构造函数创建一个参数,则需要传入BlockingQueue作为参数来创建ThreadPoolExecutor。根据您传入的队列类型,执行程序可能采取不同的行动。

答案 2 :(得分:1)

这是一个Queue实现,另外支持

操作
  

在检索元素时等待队列变为非空,

  

存储时等待队列中的空间可用   元件。

如果您需要上述功能,则Queue实施后会使用Blocking Queue

答案 3 :(得分:0)

BlockingQueue对于序列化彼此依赖的并行操作也很有用。

为了带来一个具体的(虽然有点武断)示例,here是对callInPatient()需要与registerPatientToAppointment()并行启动的实时患者队列Web应用程序的并行测试,但需要等到registerPatientToAppointment()完成才能执行callPatientInAtDoctorsOffice()

public class ClinicPatientQueueAppTest extends ParallelTest {

    private static final BlockingQueue WAIT_FOR_REGISTRATION_QUEUE = new ArrayBlockingQueue(2);

    @Test
    public void callInPatient() {
        loginToDoctorsOffice("user", "password");
        waitUntilRegistrationCompleted();  // <--
        callPatientInAtDoctorsOffice();
    }

    @Test
    public void registerPatientToAppointment() {
        registerPatientAtRegistrationKiosk("Patient Peter");
        notifyRegistrationCompleted(); // <--
    }

    private void waitUntilRegistrationCompleted() {
        WAIT_FOR_REGISTRATION_QUEUE.take();
    }

    private void notifyRegistrationCompleted() {
        WAIT_FOR_REGISTRATION_QUEUE.put(this);
    }

}
豫ICP备18024241号-1