Your code seems too complicated - I would simply write:
while (true) {
synchronized(queue) {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException ignored) {
//don't ignore me please
//you probably should exit the loop and return here...
}
}
r = queue.removeFirst(); //Why use a cast? Use generics instead.
}
}
The only situation where queue.removeFirst()
could throw a NoSuchElementException is if it is modified concurrently, which is not possible if all accesses to the queue are made in synchronized blocks.
So find the place where you access the queue without holding the lock on the monitor and you will solve your problem.
The reason why you must call wait
within a loop is that wait might wake spuriously (i.e. because wait wakes up does not mean your condition has become true so you need to test it again).
As a side note, if you used a BlockingQueue you would not have to worry about those low level details and you could simply write:
while(true) {
Runnable r = queue.take(); //blocks until queue is not empty
}