Using notifyAll and wait in Java is tricky to do correctly, you'd have a much easier chance using concurrency primitives that wrap these functions, like CountDownLatch[1] for one offs, or Condition[2].
System.currentTimeMillis is also not guaranteed to be monotonic, and System.nanoTime should be used instead. This would of course be obviated if a better concurrency primitive were to be used.