My understanding is that when you call notifyAll(), all the objects waiting in the pool to be notified are moved out of waiting state. But only one of them can acquire a lock on the object. The other threads which are now waiting for the lock (not for notification) may acquire the object lock whenever it becomes available. You could modify your code to get the desired effect by using notify().
BTW, I haven't gone thru your code
Based my explanation on the situation you described.