There are pretty much implementations already existing in the java.util.concurrent package. E.g. - ArrayBlockingQueue, DelayQueue, LinkedBlockingQueue, PriorityBlockingQueue, SynchronousQueue.
Also wait() and notify() have not been replaced. New utilities have been introduced that provide additional functionalities and performance benefits. See for example the java.util.concurrent.locks package.
I would recommend you to read this introduction. It provides a high overview that should answer your question.
Cheers.
Edit 1: Ok, then for example you can use an implementation of java.util.concurrent.locks
.Lock to implement a dequeue operation that times-out and in the same time grants fairness to the threads accessing the queue. Such implementation is ReentrantLock which has a constructor that accepts the fairness policy. The timed tryLock() favors this property. Also you can add some debugging support for counting the waiting threads on the queue, etc. This would be much more difficult to implement simply with wait() and notify() I assume.
In conclusion ReentrantLock is "better" than the low level counterparts in its extended capabilities. The basic behavior is the same though. If you do not need these extras wait() and notify() are still acceptable alternative.