在使用 BlockingQueue
的应用程序中,我面临一个新需求,该需求只能通过迭代队列中存在的元素来实现(以提供有关其中元素当前状态的信息)。
根据 API Javadoc
只要求 BlockingQueue 实现的排队方法是线程安全的。 Other API methods
(例如,从 Collection interface
继承的那些)可能不能同时使用,尽管我不确定这是否也适用于单纯的读取访问...
我可以安全地使用 iterator() WITHOUT altering the producer/consumer threads
,它可以随时与队列交互吗?我不需要 100% consistent iteration
(在迭代队列时是否看到添加/删除元素并不重要),但我不想以讨厌的 ConcurrentModificationExceptions
结束。
请注意,该应用程序当前使用的是 LinkedBlockingQueue
,但我可以自由选择任何其他 (unbounded) BlockingQueue implementation
(包括 free open-source third-party implementations
)。另外,我不想依赖将来可能会损坏的东西,所以我想要一个根据 API
确定的解决方案,而不仅仅是碰巧与 current JRE
一起使用。
最佳答案
实际上,BlockingQueue
的 Java 8 javadoc 说明了这一点:
javadoc 中没有任何内容说明这仅适用于 BlockingQueue
API 本身中指定的方法。
基本上,是的。 Iterator
面对并发修改的行为在实现类 javadocs 中指定。对于 LinkedBlockingQueue
, javadoc 指定 Iterator
返回的 iterator()
是 weakly consistent 。这意味着(例如)如果队列在迭代时被修改,您的应用程序将不会获得 ConcurrentModificationException
,但不能保证迭代看到所有队列条目。
1 - javadoc 提到批量操作可能是非原子的,但非原子并不意味着非线程安全。这里的意思是,其他一些线程可能会在某些条目已添加(或删除,或其他)而其他条目尚未添加的状态下观察队列。
@John Vint 警告:
如果 Oracle 决定更改 javadoc 中指定的行为,那将成为迁移的障碍。过去的历史表明,Sun/Oracle 避免做那种事情。