Reputation: 419
In an application which uses a BlockingQueue
, I am facing a new requirement that can only be implemented by iterating over the elements present in the queue (to provide info about the current status of the elements in there).
According to the API Javadoc
only the queueing methods of a BlockingQueue implementation are required to be thread-safe. Other API methods
(eg. those inherited from the Collection interface
) may not be used concurrently, though I am not sure whether this also applies to mere read access...
Can I safely use iterator() WITHOUT altering the producer/consumer threads
which may normally interact with the queue at any time? I have no need for a 100% consistent iteration
(it does not matter whether I see elements added/removed while iterating the queue), but I don't want to end up with nasty ConcurrentModificationExceptions
.
Note that the application is currently using a LinkedBlockingQueue
, but I am free to choose any other (unbounded) BlockingQueue implementation
(including free open-source third-party implementations
). Also, I don't want to rely on things that may break in the future, so I want a solution that is OK according to the API
and does not just merely happen to work with the current JRE
.
Upvotes: 5
Views: 6074
Reputation: 719596
Actually, the Java 8 javadoc for BlockingQueue
states this:
BlockingQueue
implementations are thread-safe.
Nothing in the javadoc says1 that this only applies to the methods specified in the BlockingQueue
API itself.
Can I safely use iterator() WITHOUT altering the producer/consumer threads which may normally interact with the queue at any time?
Basically, yes. The Iterator
's behavior in the face of concurrent modifications is specified in the implementation class javadocs. For LinkedBlockingQueue
, the javadoc specifies that the Iterator
returned by iterator()
is weakly consistent. That means (for example) that your application won't get a ConcurrentModificationException
if the queue is modified while it is iterating, but the iteration is not guaranteed to see all queue entries.
1 - The javadoc mentions that the bulk operations may be non-atomic, but non-atomic does not mean non-thread-safe. What it means here is that some other thread may observe the queue in state where some entries have been added (or removed, or whatever) and others haven't.
@John Vint warns:
Keep in mind, this is as of Java 8 and can change.
If Oracle decided to alter the behavior specified in the javadoc, that would be an impediment to migration. Past history shows that Sun / Oracle avoid doing that kind of thing. (Though that doesn't mean that it cannot happen.)
Upvotes: 6
Reputation: 40266
Yes, you can iterate over the entire queue. Looking at LinkedBlockingQueue
and ArrayBlockingQueue
implementations you do have a side effect. When constructing and operating the Iterator
there are three places where full locks are acquired.
next()
remove()
Keep in mind, this is as of Java 8 and can change.
So, yes you do get to iterate safely, but you will effect the performace of put
s and offer
s.
Now for your question, does BlockingQueue
offer safe iteration? The answer there is it depends on the implementation. There could be a future BlockingQueue implementation that will throw a UnsupportedOperationException
.
Upvotes: 4