同时迭代BlockingQueue

时间:2016-06-21 13:35:24

标签: java multithreading concurrency blockingqueue

在使用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一起工作。

2 个答案:

答案 0 :(得分:5)

实际上,BlockingQueue的Java 8 javadoc声明了这一点:

  

BlockingQueue实现是线程安全的。

javadoc中没有任何内容说 1 ,这只适用于BlockingQueue API本身中指定的方法。

  

我可以安全地使用iterator()而无需改变通常可能随时与队列交互的生产者/消费者线程吗?

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

1 - javadoc提到批量操作可能是非原子操作,但非原子操作并不意味着非线程安全。这意味着其他一些线程可能会在某些条目被添加(或删除,或其他)的状态下观察队列,而其他线程则没有。

@John Vint警告说:

  

请记住,这与Java 8一样,可以更改。

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

答案 1 :(得分:3)

是的,您可以遍历整个队列。查看LinkedBlockingQueueArrayBlockingQueue实现,您会产生副作用。在构造和操作Iterator时,有三个地方可以获得完全锁定。

  1. 施工期间
  2. 调用next()
  3. 调用remove()
  4. 请记住,这与Java 8一样,可以更改。

    所以,是的,你确实可以安全地进行迭代,但是你会影响putoffer的性能。

    现在针对您的问题,BlockingQueue是否提供安全迭代?答案取决于实施。未来的BlockingQueue实现可能会抛出UnsupportedOperationException