I was trying to use the iterator methods on a BlockingQueue and discovered that hasNext() is non-blocking – i.e. it will not wait until more elements are added and will instead return false when there are no elements.
So here are the questions :
- Is this bad design, or wrong
expectation? - Is there a way to use the blocking
methods of the BLockingQueue with
its parent Collection class methods
(e.g. if some method were expecting
a collection, can I pass a blocking
queue and hope that its processing
will wait until the Queue has more
elements)
Here is a sample code block
public class SomeContainer{
public static void main(String[] args){
BlockingQueue bq = new LinkedBlockingQueue();
SomeContainer h = new SomeContainer();
Producer p = new Producer(bq);
Consumer c = new Consumer(bq);
p.produce();
c.consume();
}
static class Producer{
BlockingQueue q;
public Producer(BlockingQueue q) {
this.q = q;
}
void produce(){
new Thread(){
public void run() {
for(int i=0; i<10; i++){
for(int j=0;j<10; j++){
q.add(i+" - "+j);
}
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
}
}
static class Consumer{
BlockingQueue q;
public Consumer(BlockingQueue q) {
this.q = q;
}
void consume() {
new Thread() {
public void run() {
Iterator itr = q.iterator();
while (itr.hasNext())
System.out.println(itr.next());
}
}.start();
}
}
}
This Code only prints the iteration once at the most.
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.Yes, for instance by extending the class and overriding the
nextandhasNextmethods to use blocking routines instead. Note thathasNextwould need to always returntruein this case – which again violates the contract.