The difference is relatively simple.
BLOCKED state, a thread is about to enter a
synchronized block, but there is another thread currently running inside a
synchronized block on the same object. The first thread must then wait for the second thread to exit its block.
WAITING state, a thread is waiting for a signal from another thread. This happens typically by calling
Thread.join(). The thread will then remain in this state until another thread calls
Object.notify(), or dies.