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 forBlockingQueue
说明:
BlockingQueue
实现是线程安全的
javadoc中没有任何内容表明这只适用于BlockingQueue
API本身中指定的方法
我可以安全地使用迭代器()而不改变生产者/消费者线程吗?生产者/消费者线程通常会在任何时候与队列进行交互
基本上,是的。迭代器在并发修改时的行为在实现类javadocs中指定。对于LinkedBlockingQueue
,指定由Iterator()
返回的Iterator
为。这意味着(例如)如果队列在迭代过程中被修改,那么应用程序将不会获得ConcurrentModificationException
,但是迭代不能保证看到所有队列条目
1-javadoc提到批量操作可能是非原子的,但非原子并不意味着非线程安全。这里的意思是,其他一些线程可能会观察到队列的状态,其中一些条目已被添加(或删除,或其他任何内容),而其他条目未被添加
@约翰·温特警告说:
请记住,这是从Java8开始的,可以更改
如果Oracle决定改变javadoc中指定的行为,这将成为迁移的障碍。过去的历史表明Sun/Oracle避免做这种事情。好的,我重新阅读了API,可能失败的只是批量操作(addAll()等)。感谢您确认迭代是安全的!是的,你是对的,甲骨文很可能不会改变它。然而,每当我在查看源代码的基础上回答问题时,我总是给出这个警告,因为它没有文档记录。总的来说,你是对的。实施细节可能会在没有太多公告的情况下发生变化。具有明确指定行为的API不应该出现。@StephenC“……但迭代不能保证看到所有队列条目。”那么这是否发生了变化?迭代是否保证能看到所有元素?@emu“……但迭代不保证能看到所有队列条目。”那么这是否发生了变化?迭代是否保证看到所有元素?我不担心不支持的操作异常。LinkedBlockingQueue至少支持文档中的所有收集方法,但我知道其他实现可能不支持。