【问题标题】:Java: ArrayBlockingQueue vs. LinkedBlockingQueueJava:ArrayBlockingQueue 与 LinkedBlockingQueue
【发布时间】:2013-06-08 08:26:46
【问题描述】:

我认为,在大多数情况下,ArrayBlockingQueue 的性能将优于LinkedBlockingQueue。但是,当数组中总是有足够的空间时就是这种情况……如果它已满,那么它是否会表现得这么好就不是很可预测了,因为它会阻塞试图将数据推送到队列中的线程。 .

所以,我的问题是:BlockingQueue 是否有任何中间实现?比如,ArrayListBlockingQueueBucketListBlockingQueue?类似于数组列表的东西,这样队列可以动态增加容量,同时仍然可以从使用数组最终存储数据中获得合理的好处?

【问题讨论】:

  • 数组列表不会提高性能...为什么会这样?此外:您为什么担心性能?你真的有问题吗?你有简介吗?
  • 我在考虑内存局部性。如果您使用其元素在随机内存地址周围跳转的链表,则更有可能出现缓存未命中和类似问题。另外,要从内存中获取,您必须获取下一个元素的地址,然后获取该地址的内容......而对于数组,您只需执行 address++ 即可获取下一个元素的地址。使用数组列表,您会在两种实现之间做出一些妥协……您认为不是吗?
  • 我认为数组列表给你带来的好处都不是原始集合。您仍然必须分配内存,并且根据数组的大小,它会或多或少地碎片化。我认为,如果您使基于数组的集合大小调整算法正确,您将几乎没有调整大小和非常快速的迭代。至于内存局部性 - 集合存储对对象的引用,这些对象本身可能位于内存中的任何位置,因此在这方面您可能不会从使用一个集合或其他集合中获得任何收益。

标签: java multithreading synchronization queue


【解决方案1】:

我的 2 美分:

首先,这里的底线是您并不真正关心这里的差异,因为即使您使用普通的 LinkedBlockingQueue,当您交付一些微秒级系统时,性能也足够好。所以这里的性能差异并没有那么大。

如果您正在编写任务关键型高性能系统,并且您正在使用队列在线程之间传递消息,您始终可以通过 [队列大小] = [最大可接受延迟] * [最大消息速率] 来估算所需的队列大小.任何可以超过这种容量的东西都意味着你会遇到消费缓慢的问题。在关键任务应用程序中,这种延迟意味着您的系统出现故障。可能需要一些手动过程来确保系统正常运行。

如果您的系统不是关键任务,您可以简单地暂停(阻止)发布者,直到一些消费者可用。

【讨论】:

    【解决方案2】:

    1 . LinkedBlockingQueueLinkedList 实现但不完全是LinkedList 的JDK 实现。它使用static inner class Node 来维护元素之间的链接)

    Constructor for LinkedBlockingQueue
    public LinkedBlockingQueue(int capacity) 
    {
            if (capacity < = 0) throw new IllegalArgumentException();
            this.capacity = capacity;
            last = head = new Node< E >(null);   // Maintains a underlying linkedlist. ( Use when size is not known )
    }
    

    Node 用于维护链接的类

    static class Node<E> {
        E item;
        Node<E> next;
        Node(E x) { item = x; }
    }
    

    2 。 ArrayBlockingQueue(数组实现)

    ArrayBlockingQueue 的构造函数

    public ArrayBlockingQueue(int capacity, boolean fair) 
    {
                if (capacity < = 0)
                    throw new IllegalArgumentException();
                this.items = new Object[capacity]; // Maintains a underlying array
                lock = new ReentrantLock(fair);
                notEmpty = lock.newCondition();
                notFull =  lock.newCondition();
    }
    

    ArrayBlockingQueueLinkedBlockingQueue 之间的最大区别从构造函数中可以看出,一个具有Array 和另一个LinkedList 的底层数据结构。

    ArrayBlockingQueue 使用 single-lock double condition algorithmLinkedBlockingQueue 是“双锁队列”算法的变体,它有 2 个锁 2 个条件(takeLock,putLock)

    到目前为止,我对这两种实现进行了比较回到原来的问题,在这个 doug Lea 谈到 DynamicArrayBlockingQueue 时,concurrency mailing list 提出了类似的问题,即implementation provided by Dawid Kurzyniec.

    【讨论】:

    • 我在这里看到一票否决如果您不同意答案,请同时提供 cmets,以便我可以改进或更正,如果有问题。
    • 为了更清楚 ArrayBlockingQueue 使用 Circular Array 作为底层结构 +1 回答
    猜你喜欢
    • 2010-11-28
    • 2013-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多