BlockingQueue的drainTo()方法的线程安全性

BlockingQueue的文档说批量操作不是线程安全的,尽管它没有明确提到方法drainTo()。

BlockingQueue实现是线程安全的。 所有排队方法都使用内部锁或其他forms的并发控制以primefaces方式实现其效果。 但是,除非在实现中另有说明,否则批量收集操作addAll,containsAll,retainAll和removeAll不一定以primefaces方式执行。 因此,例如,在仅添加c中的一些元素之后,addAll(c)可能会失败(抛出exception)。

drainTo()方法的文档指定无法以线程安全的方式修改BlockingQueue元素所用的集合。 但是,它没有提到有关drainTo()操作是线程安全的任何事情。

从此队列中删除所有可用元素,并将它们添加到给定集合中。 此操作可能比重复轮询此队列更有效。 尝试向集合c添加元素时遇到的故障可能导致在抛出关联的exception时元素既不在集合中,也不在集合中。 尝试将队列排放到自身会导致IllegalArgumentException。 此外,如果在操作正在进行时修改指定的集合,则此操作的行为是不确定的。

那么,drainTo()方法是线程安全的吗? 换句话说,如果一个线程在阻塞队列上调用了drainTo()方法,而另一个线程在同一个队列上调用了add()或put(),那么两个操作结束时队列的状态是否一致?

我认为你混淆了“线程安全”和“primefaces”这两个术语。 它们并不意味着同样的事情。 方法可以是线程安全的而不是primefaces的,并且可以是primefaces的(对于单个线程)而不是线程安全的。

线程安全是一个橡胶术语,如果不是循环的话很难定义。 根据Goetz的说法,一个好的工作模型是,如果一个方法在multithreading上下文中使用时“正确”是一个线程安全的,因为它在单线程上下文中运行。 除非你有一个正式的规范来衡量,否则正确性是主观的。

相比之下,primefaces很容易定义。 它只是意味着操作完全发生或根本不发生。

所以你的问题的答案是drainTo()是线程安全的,但不是primefaces的。 它不是primefaces的,因为它可以通过排水中途抛出exception。 但是,以模数表示,队列仍将处于一致状态,无论其他线程是否同时对队列执行操作。


(在上面的讨论中隐含的是, BlockingQueue接口的具体实现正确地实现了接口。如果没有,所有的赌注都会关闭。)

drainTo()是线程安全的,因为队列上同时发生的任何操作都不会改变结果,也不会破坏队列的状态。 否则,该方法将毫无意义。

如果目标集合(添加结果的集合)执行“聪明”的操作,则可能会遇到问题。 但是,由于您通常将队列排放到只有一个线程可以访问的集合,因此更多的是理论问题。