Of course, I could have written that pop function as T remove() { for (;;) { e.wait; synchronized(this) { if (queue.length != 0) { e.signal; return remove_item_from_queue; } } } } And of course I'm assuming that add_item_to_queue and remove_item_from_queue will adjust queue.length. If not, you'd keep a count variable.