Разница между состояниями WAIT и BLOCKED

В чем разница между состоянием состояния WAIT и состоянием BLOCKED?

Документация Thread.State:

Заблокированные
В этом состоянии находится поток, который заблокирован в ожидании блокировки монитора.

Ожидание
Нить, которая бесконечно ждет другого потока для выполнения определенного действия, находится в этом состоянии

не объясняет мне разницу.

Ответ 1

Поток переходит в состояние ожидания, когда он вызывает wait() объекта. Это называется состоянием Ожидание. Как только поток достигнет состояния ожидания, ему нужно будет подождать до некоторого другого потока notify() или notifyAll() объекта.

Как только этот поток будет уведомлен, он не будет запущен. Возможно, что другие потоки также уведомлены (используя notifyAll()), или первый поток не завершил свою работу, поэтому он по-прежнему блокируется, пока не получит свой шанс. Это называется Заблокировано.

После того, как останутся другие потоки и вероятность этого потока, он переходит в состояние Runnable после того, как он имеет право набрать работу на основе механизма потоковой передачи JVM и переходит в состояние выполнения.

Ответ 2

Отличие относительно просто.

В состоянии BLOCKED поток вот-вот войдет в блок synchronized, но есть еще один поток, который в настоящее время выполняется внутри блока synchronized на том же самом объекте. Первый поток должен ждать, пока второй поток выйдет из своего блока.

В состоянии WAITING поток ожидает сигнала из другого потока. Обычно это происходит при вызове Object.wait() или Thread.join(). Затем поток будет оставаться в этом состоянии, пока другой поток не вызовет Object.notify() или не умрет.

Ответ 3

Упрощенная перспектива для интерпретации дампов потоков:
ПОДОЖДИТЕ. Я жду, чтобы мне дали какую-то работу, поэтому я сейчас простаиваю. BLOCKED. Я занят попыткой выполнить работу, но на моем пути стоит еще один поток, поэтому я сейчас простаиваю. RUNNABLE... (Native Method) - я вызвал, чтобы запустить какой-то собственный код (который еще не закончен), поскольку JVM имеет значение RUNNABLE, и он не может дать никакой дополнительной информации. Общим примером может быть собственный метод прослушивания сокетов, закодированный в C, который на самом деле ждет, пока какой-либо трафик не поступит, поэтому я сейчас простаиваю. В этой ситуации это можно рассматривать как особый вид WAIT, поскольку мы на самом деле не работаем (без процессора), но вам придется использовать дамп потока операционной системы, а не дамп потока Java, чтобы увидеть его.

Ответ 4

Заблокировано. Ваш поток находится в текущем состоянии жизненного цикла потока и пытается получить блокировку объекта. Wait - ваш поток находится в ожидании состояния жизненного цикла потока и ожидает, пока сигнал уведомления войдет в текущее состояние потока.

Ответ 5

Важным отличием между заблокированным и ожидающим состояниями является влияние на планировщик. Нить в заблокированном состоянии является частью waitset, борющейся за блокировку; этот поток по-прежнему считается чем-то, что планировщик должен обслуживать, возможно, влияя на его решения о том, сколько времени требуется для выполнения текущих потоков.

Как только поток находится в состоянии ожидания, стресс, который он накладывает на систему, минимизируется, и планировщику не нужно беспокоиться об этом. Он неактивен, пока не получит уведомление. За исключением того факта, что он поддерживает занятый поток ОС, он полностью вышел из игры.

Вот почему использование notifyAll менее чем идеально, оно вызывает кучу потоков, которые ранее были бездействующими, не загружая систему, чтобы проснуться, где большинство из них блокируется, пока они не смогут получить блокировку, найти условие, которого они ждут, неверно, и возвращайтесь к ожиданию. Было бы предпочтительнее уведомлять только те потоки, которые имеют шанс добиться прогресса.

Ответ 6

см. этот пример:

демонстрация состояний потоков.

/*NEW- thread object created, but not started.
RUNNABLE- thread is executing.
BLOCKED- waiting for monitor after calling wait() method.
WAITING- when wait() if called & waiting for notify() to be called.
  Also when join() is called.
TIMED_WAITING- when below methods are called:
 Thread.sleep
 Object.wait with timeout
 Thread.join with timeout
TERMINATED- thread returned from run() method.*/
public class ThreadBlockingState{

public static void main(String[] args) throws InterruptedException {
    Object obj= new Object();
    Object obj2 = new Object();
    Thread3 t3 = new Thread3(obj,obj2);
    Thread.sleep(1000);
    System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+
            ",when Wait() is called & waiting for notify() to be called.");
    Thread4 t4 = new Thread4(obj,obj2);
    Thread.sleep(3000);
    System.out.println("nm:"+t3.getName()+",state:"+t3.getState().toString()+",After calling Wait() & waiting for monitor of obj2.");
    System.out.println("nm:"+t4.getName()+",state:"+t4.getState().toString()+",when sleep() is called.");
}

}
class Thread3 extends Thread{
Object obj,obj2;
int cnt;
Thread3(Object obj,Object obj2){
    this.obj = obj;
    this.obj2 = obj2;
    this.start();
}

@Override
public void run() {
    super.run();
    synchronized (obj) {
        try {
            System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before Wait().");
            obj.wait();             
            System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After Wait().");
            synchronized (obj2) {
                cnt++;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}
class Thread4 extends Thread{
Object obj,obj2;
Thread4(Object obj,Object obj2){
    this.obj = obj;
    this.obj2 = obj2;
    this.start();
}

@Override
public void run() {
    super.run();
    synchronized (obj) {
        System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",Before notify().");
        obj.notify();
        System.out.println("nm:"+this.getName()+",state:"+this.getState().toString()+",After notify().");
    }
    synchronized (obj2) {
        try {
            Thread.sleep(15000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
}