Why does the iterator.hasNext not work with BlockingQueue?
Just don't use iterators with Queues. Use peek()
or poll()
instead or take()
if it's a BlockingQueue
:
void consume() { new Thread() { @Override public void run() { Object value; // actually, when using a BlockingQueue, // take() would be better than poll() while ((value=q.poll())!=null) System.out.println(value); } }.start();}
A Queue
is an Iterable
because it is a Collection
and hence needs to provide an iterator()
method, but that shouldn't ever be used, or you shouldn't be using a Queue in the first place.
1) Is this bad design, or wrong expectation?
Wrong expectations since it would otherwise violate the contract of Iterator which on Iterator.next()
says: Throws: NoSuchElementException - iteration has no more elements.
If next()
would block the exception would never be thrown.
2) Is there a way to use the blocking methods
Yes, for instance by extending the class and overriding the next
and hasNext
methods to use blocking routines instead. Note that hasNext
would need to always return true
in this case - which again violates the contract.
if an iterator blocked on hasNext
then the iteration would never finish unless you explicitly broke out of it, this would be quite a strange design.
In any case the LinkedBlockingQueue
javadoc has this to say
Returns an iterator over the elements in this queue in proper sequence. The returned <tt>Iterator</tt> is a "weakly consistent" iterator that will never throw {@link ConcurrentModificationException}, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.