In Java we have Objects.wait() and Unsafe.park() methods. Both of them will suspend the running thread & put it in waiting state. But these two methods work on different principles.
Object.wait() method works on monitor based synchronization. So that works well with "happens-before" relationship in Java. To bring back a waiting thread in runnable state, we will use Object.notify() method on the same monitor object. So when the thread comes back to runnable state, it will surely get updated values of the variables shared across multiple threads. JVM will make sure thread state is synchronized with main memory, but that is the additional overhead.
Unsafe.park() method takes the thread as an argument. To move back a parked thread to runnable state, we need to call Unsafe.unpark() method on the same thread. It works on permit basis. When Unsafe.unpark() is called, it will unblock the thread if it is already parked or will make sure the next park call on the thread is unblocked immediately. So its performance should be better as no synchronization is required with main memory. That's why thread pool in general (for example ExecutorService) use park method while waiting for tasks from the blocking queue.
As you can see, these use cases are different. If you have state that is shared across threads & you want to make sure one thread should wait for other thread before proceeding with the update, then you should go ahead with wait() and notify() methods. As an application developer, mostly you won't have to use park() method, it's too low level of an API.