Java 在BlockingQueue上并发迭代

Java 在BlockingQueue上并发迭代,java,multithreading,concurrency,blockingqueue,Java,Multithreading,Concurrency,Blockingqueue,在一个使用阻塞队列的应用程序中,我面临着一个新的需求,它只能通过迭代队列中存在的元素来实现(提供队列中元素的当前状态信息) 根据API Javadoc,只有BlockingQueue实现的排队方法才需要是线程安全的其他API方法(例如从收集接口继承的方法)可能不能同时使用,尽管我不确定这是否也适用于单纯的读取访问 我是否可以安全地使用迭代器(),而不改变生产者/消费者线程,该线程通常会在任何时候与队列交互?我不需要进行100%一致的迭代(我在迭代队列时是否看到添加/删除的元素并不重要),但我不想

在一个使用
阻塞队列
的应用程序中,我面临着一个新的需求,它只能通过迭代队列中存在的元素来实现(提供队列中元素的当前状态信息)

根据
API Javadoc
,只有BlockingQueue实现的排队方法才需要是线程安全的<代码>其他API方法(例如从
收集接口继承的方法
)可能不能同时使用,尽管我不确定这是否也适用于单纯的读取访问

我是否可以安全地使用迭代器(),而不改变生产者/消费者线程,该线程通常会在任何时候与队列交互?我不需要进行
100%一致的迭代
(我在迭代队列时是否看到添加/删除的元素并不重要),但我不想以令人讨厌的
ConcurrentModificationException
结束


请注意,应用程序当前使用的是
LinkedBlockingQueue
,但我可以自由选择任何其他
(无边界)BlockingQueue实现
(包括
免费开源第三方实现
)。另外,我不想依赖于将来可能出现的问题,因此我想要一个根据
API
可以解决的解决方案,而不仅仅是碰巧使用
当前的JRE

是的,您可以迭代整个队列。查看
LinkedBlockingQueue
ArrayBlockingQueue
实现,您确实有副作用。在构造和操作
迭代器时,有三个位置可以获取完全锁

  • 施工期间
  • 调用
    next()
  • 调用
    remove()时
  • 请记住,这是从Java8开始的,可以更改

    因此,是的,您确实可以安全地进行迭代,但是您将影响
    put
    s和
    offer
    s的性能


    现在来回答您的问题,
    BlockingQueue
    是否提供了安全的迭代?答案是,这取决于实施情况。将来可能会有一个BlockingQueue实现,它将抛出一个
    不支持操作异常

    实际上,Java 8 for
    BlockingQueue
    说明:

    BlockingQueue
    实现是线程安全的

    javadoc中没有任何内容表明这只适用于
    BlockingQueue
    API本身中指定的方法

    我可以安全地使用迭代器()而不改变生产者/消费者线程吗?生产者/消费者线程通常会在任何时候与队列进行交互

    基本上,是的。
    迭代器在并发修改时的行为在实现类javadocs中指定。对于
    LinkedBlockingQueue
    ,指定由
    Iterator()
    返回的
    Iterator
    为。这意味着(例如)如果队列在迭代过程中被修改,那么应用程序将不会获得
    ConcurrentModificationException
    ,但是迭代不能保证看到所有队列条目


    1-javadoc提到批量操作可能是非原子的,但非原子并不意味着非线程安全。这里的意思是,其他一些线程可能会观察到队列的状态,其中一些条目已被添加(或删除,或其他任何内容),而其他条目未被添加


    @约翰·温特警告说:

    请记住,这是从Java8开始的,可以更改


    如果Oracle决定改变javadoc中指定的行为,这将成为迁移的障碍。过去的历史表明Sun/Oracle避免做这种事情。

    好的,我重新阅读了API,可能失败的只是批量操作(addAll()等)。感谢您确认迭代是安全的!是的,你是对的,甲骨文很可能不会改变它。然而,每当我在查看源代码的基础上回答问题时,我总是给出这个警告,因为它没有文档记录。总的来说,你是对的。实施细节可能会在没有太多公告的情况下发生变化。具有明确指定行为的API不应该出现。@StephenC“……但迭代不能保证看到所有队列条目。”那么这是否发生了变化?迭代是否保证能看到所有元素?@emu“……但迭代不保证能看到所有队列条目。”那么这是否发生了变化?迭代是否保证看到所有元素?我不担心不支持的操作异常。LinkedBlockingQueue至少支持文档中的所有收集方法,但我知道其他实现可能不支持。