Given the difficulty of using wait and notify correctly, you should use the higher-level concurrency utilities instead.
Not only are they hard to use and likely to introduce mistakes - they also make code hard to read because understanding how they work generally requires global knowledge of the code being synchronized. Higher level abstractions are generally free of this