Разница между состояниями ожидания и заблокированного потока


в чем разница между состоянием потока ожидания и состоянием потока заблокирован?

The нить.Государственная документация:

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

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

не объяснить разница для меня.

6 65

6 ответов:

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

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

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

разница относительно проста.

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

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

упрощенная перспектива для интерпретации дампов потоков:

  • ждать - Я жду, чтобы мне дали какую-то работу, поэтому я сейчас бездельничаю.
  • заблокирован - Я занят, пытаясь получить работу, но в другой поток стоит на моем пути, так что я холостой прямо сейчас.
  • RUNNABLE...(Собственный метод) - я вызвал, чтобы запустить некоторый собственный код (который еще не закончен), так как JVM обеспокоенный, вы управляемы, и он не может дать никакой дополнительной информации. Общим примером может быть собственный метод прослушивателя сокетов, закодированный на C, который фактически ожидает поступления любого трафика, поэтому я сейчас простаиваю. В этой ситуации это можно рассматривать как особый вид ожидания, поскольку мы на самом деле не работаем (без ожога процессора), но вам придется использовать дамп потока ОС, а не дамп потока Java, чтобы увидеть его.

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

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

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

(использование ReentrantLock вместо встроенных блокировок позволяет вам иметь несколько условий для одной блокировки, так что вы можете убедиться, что уведомленный поток-это тот, который ждет определенного условия, избегая ошибки потерянного уведомления в случае получения потоком уведомления о чем-то, на что он не может действовать.)

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

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

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

/*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();
        }
    }
}
}